#ifdef __cplusplus
#if __cplusplus
extern "C"
{
#endif
#endif /* End of #ifdef __cplusplus */
#include "platform.h"


static pthread_t g_IspPid[ISP_MAX_DEV_NUM] = {0};
static HI_U32 g_au32IspSnsId[ISP_MAX_DEV_NUM] = {0, 1};

int copyefile=0;                                        //1=U盘拷贝状态,0=非拷贝状态:
int video_freeze_state = 0;                             //1=冻结状态,0=非冻结状态
int record = 0;                                         //1=录像状态,0=非录像状态
int nosignal= 0;                                        //1=无信号状态,0=有信号状态
int MWB_State=0;                                        //1=白平衡状态,0=非白平衡状态;
int delete_file=0;                                      //1=正在删除状态,0=删除完毕状态;  

int hdmi_disp_mode = HDMI_1080P;
int hdmi_size; //    = 2;
unsigned char *fbp;
unsigned char osdBuf[SCREEN_WIDTH * SCREEN_HEIGHT * 4]; // MIPI的OSD buffer
unsigned char osdBufHdmi[1920 * 1080 * 4];              // HDMI的OSD buffer
unsigned char ucguiBuf[1920 * 1080 * 4] = {0};          // UC_GUI的buffer

static SAMPLE_VENC_GETSTREAM_PARA_S gs_stPara;
static pthread_t gs_VencPid;

VPSS_CHN VpssChn;                                       // VPSS通道
SAMPLE_VI_CONFIG_S stViConfig;                          //摄像头输入模式:MIPI & DVP
SAMPLE_VO_CONFIG_S stVoConfig;                          //显示输出模式：触摸屏&HDMI

//=======================================================================================================
//摄像头结构体
//=======================================================================================================
// 结构体定义
SAMPLE_SNS_TYPE_E g_enSnsType[MAX_SENSOR_NUM] =
  {
    OS01A,
    OV426,
    OV9734
  };


//=======================================================================================================
//=======================================================================================================
// OV9734
//=======================================================================================================
//=======================================================================================================
// 结构体赋值  OV9734 摄像头属性
combo_dev_attr_t MIPI_4lane_CHN0_SENSOR_OV9734_10BIT_4M_NOWDR_ATTR =
{
        .devno = 0,
        .input_mode = INPUT_MODE_MIPI,
        .data_rate = MIPI_DATA_RATE_X1,
        .img_rect = {0, 0, 720, 720},
        {.mipi_attr =
             {
                 DATA_TYPE_RAW_10BIT,
                 HI_MIPI_WDR_MODE_NONE,
                 {0, -1, -1, -1}
              }
        }
};
//=======================================================================================================
// 结构体赋值  OV9734
//=======================================================================================================
VI_DEV_ATTR_S DEV_ATTR_OV9734_4M_BASE =
    {
        VI_MODE_MIPI,
        VI_WORK_MODE_1Multiplex,
        {0x0FFF0000, 0x0},
        VI_SCAN_PROGRESSIVE,
        {-1, -1, -1, -1},
        VI_DATA_SEQ_YUYV,
        {/*port_vsync   port_vsync_neg     port_hsync        port_hsync_neg        */
         VI_VSYNC_FIELD,
         VI_VSYNC_NEG_HIGH,
         VI_HSYNC_VALID_SINGNAL,
         VI_HSYNC_NEG_HIGH,
         VI_VSYNC_VALID_SINGAL,
         VI_VSYNC_VALID_NEG_HIGH,
         /*hsync_hfb    hsync_act    hsync_hhb*/
         {0, 720, 0,
          /*vsync0_vhb vsync0_act vsync0_hhb*/
          0, 720, 0,
          /*vsync1_vhb vsync1_act vsync1_hhb*/
          0, 0, 0}},
        VI_DATA_TYPE_RGB,
        HI_FALSE,
        {720, 720},
        {{
             {720, 720},
         },
         {VI_REPHASE_MODE_NONE,
          VI_REPHASE_MODE_NONE}},
        {WDR_MODE_NONE,
         800},
        DATA_RATE_X1};
//=======================================================================================================
// 结构体变量赋值 OV9734
//=======================================================================================================
static VI_PIPE_ATTR_S PIPE_ATTR_720x720_RAW12_420_3DNR_RFR =
{
    VI_PIPE_BYPASS_NONE, HI_FALSE, HI_FALSE, 720, 720, PIXEL_FORMAT_RGB_BAYER_10BPP, COMPRESS_MODE_LINE, DATA_BITWIDTH_10, HI_FALSE, {PIXEL_FORMAT_RGB_BAYER_10BPP, DATA_BITWIDTH_10, VI_NR_REF_FROM_RFR, COMPRESS_MODE_NONE}, HI_FALSE, {-1, -1}
};

//=======================================================================================================
// 结构体变量赋值    输入尺寸720*720 OV9734
//=======================================================================================================
static VI_CHN_ATTR_S CHN_ATTR_720x720_420_SDR8_LINEAR =
    {
        {720, 720},
        PIXEL_FORMAT_RGB_BAYER_10BPP,
        DYNAMIC_RANGE_SDR8,
        VIDEO_FORMAT_LINEAR,
        COMPRESS_MODE_NONE,
        1,
        0,
        0,
        {-1, -1}
    };

//=======================================================================================================
// OV9734
ISP_PUB_ATTR_S ISP_PUB_ATTR_OV9734_MIPI_4M_30FPS =
    {
        {0, 0, 720, 720},
        {720, 720},
        30.0,
        BAYER_BGGR,
        WDR_MODE_NONE, // WDR_MODE_2To1_FRAME, wdr
        0,
    };

//=======================================================================================================
//=======================================================================================================
// OS01A
//=======================================================================================================
//=======================================================================================================
// OS01A 摄像头属性
combo_dev_attr_t MIPI_4lane_CHN0_SENSOR_OS01A_12BIT_4M_NOWDR_ATTR =
    {
        .devno = 0,                     // device number
        .input_mode = INPUT_MODE_MIPI,  // input mode: MIPI/LVDS/SUBLVDS/HISPI/DC
        .data_rate = MIPI_DATA_RATE_X1, // output 1 pixel per clock
        .img_rect = {0, 0, 800, 800},   // MIPI Rx device crop area (对应于原始传感器输入图像的大小)
        {
            .mipi_attr =
                {
                    DATA_TYPE_RAW_10BIT,
                    HI_MIPI_WDR_MODE_NONE,
                    {0, -1, -1, -1}
                }
        }
    };

//=======================================================================================================
// 结构体赋值  OS01A VI属性
// The attributes of a VI device
//=======================================================================================================
VI_DEV_ATTR_S DEV_ATTR_OS01A_4M_BASE =
    {
        VI_MODE_MIPI,            // RW;Interface mode ;
        VI_WORK_MODE_1Multiplex, // RW;Work mode;
        {0xFFF00000, 0x0},       // RW;Component mask
        VI_SCAN_PROGRESSIVE,     // RW;Input scanning mode (progressive or interlaced)
        {-1, -1, -1, -1},        // RW;AD channel ID. Typically, the default value -1 is recommended
        VI_DATA_SEQ_YUYV,        // RW;Input data sequence (only the YUV format is supported)
        // Sync timing. This member must be configured in BT.601 mode or DC mode
        {
            /*port_vsync   port_vsync_neg     port_hsync        port_hsync_neg        */
            VI_VSYNC_PULSE,
            VI_VSYNC_NEG_LOW,
            VI_HSYNC_VALID_SINGNAL,
            VI_HSYNC_NEG_HIGH,
            VI_VSYNC_VALID_SINGAL,
            VI_VSYNC_VALID_NEG_HIGH,
            /*hsync_hfb    hsync_act    hsync_hhb*/
            {0, 800, 0,
             /*vsync0_vhb vsync0_act vsync0_hhb*/
             0, 800, 0,
             /*vsync1_vhb vsync1_act vsync1_hhb*/
             0, 0, 0}},
        VI_DATA_TYPE_RGB, // RW;RGB: CSC-709 or CSC-601, PT YUV444 disable; YUV: default yuv CSC coef PT YUV444 enable.
        HI_FALSE,         // RW;Data reverse
        {800, 800},       // RW;Input size
        {// RW;Attribute of BAS
         {
             {800, 800},
         },
         {VI_REPHASE_MODE_NONE,
          VI_REPHASE_MODE_NONE}},
        {// RW;Attribute of WDR
         WDR_MODE_NONE,
         800},
        DATA_RATE_X1 // RW;Data rate of Device(1 pixel per clock)
};

//=======================================================================================================
// 结构体变量赋值 OS01A
// The attributes of pipe
//=======================================================================================================
static VI_PIPE_ATTR_S PIPE_ATTR_800x800_RAW12_420_3DNR_RFR =
    {
        VI_PIPE_BYPASS_NONE,
        HI_FALSE,                     // RW;YUV skip enable
        HI_FALSE,                     // RW;Range:[0,1];ISP bypass enable
        800,                          // RW;Range:[0,1];Range[VI_PIPE_MIN_WIDTH,VI_PIPE_MAX_WIDTH];Maximum width
        800,                          // RW;Range[VI_PIPE_MIN_HEIGHT,VI_PIPE_MAX_HEIGHT];Maximum height
        PIXEL_FORMAT_RGB_BAYER_10BPP, // RW;Pixel format
        COMPRESS_MODE_LINE,           // RW;Range:[0,4];Compress mode.
        DATA_BITWIDTH_10,             // RW;Range:[0,4];Bit width
        HI_FALSE,                     // RW;Range:[0,1];3DNR enable
        {// RW;Attribute of 3DNR
         PIXEL_FORMAT_RGB_BAYER_10BPP,
         DATA_BITWIDTH_10,
         VI_NR_REF_FROM_RFR,
         COMPRESS_MODE_NONE},
        HI_TRUE,  // HI_FALSE,   RW;Range:[0,1];Sharpen enable -------------------edwin 2022-03-27
        {-1, -1}, // RW;Frame rate
        HI_FALSE  // RW;Range:[0,1];when professional mode snap, whether to discard long exposure picture in the video pipe
};

//=======================================================================================================
// 结构体变量赋值 OS01A
// The attributes of channel
//=======================================================================================================
static VI_CHN_ATTR_S CHN_ATTR_800x800_420_SDR8_LINEAR =
    {
        {800, 800},                   // RW;Channel out put size
        PIXEL_FORMAT_RGB_BAYER_10BPP, // RW;Pixel format
        DYNAMIC_RANGE_SDR8,           // RW;Dynamic Range
        VIDEO_FORMAT_LINEAR,          // RW;Video format
        COMPRESS_MODE_NONE,           // RW;256B Segment compress or no compress.
        1,                            // RW;Mirror enable
        0,                            // RW;Flip enable
        0,                            // RW;Range [0,8];Depth
        {-1, -1}                      // RW;Frame rate
};
//=======================================================================================================
// 结构体变量赋值 OS01A
// ISP public attribute, contains the public image attribute
//=======================================================================================================
ISP_PUB_ATTR_S ISP_PUB_ATTR_OS01A_MIPI_4M_30FPS =
    {
        {0, 0, 800, 800}, // RW; Start position of the cropping window, image width, and image height
        {800, 800},       // RW; Width and height of the image output from the sensor
        60.0,             // RW; Range: [0, 0xFFFF]; For frame rate
        BAYER_BGGR,       // RW; Range:[0,3] ;Format:2.0;the format of the input Bayer image
        WDR_MODE_NONE,    // RW; WDR mode select
        0,                // RW; Range: [0, 0xFF]; Format: 8.0; For special sensor mode switches
    };

//=======================================================================================================
//=======================================================================================================
// OV6946
//=======================================================================================================
//=======================================================================================================
// 结构体赋值 OV426 摄像头属性
combo_dev_attr_t MIPI_4lane_CHN0_SENSOR_OV426_10BIT_4M_NOWDR_ATTR =
    {
        .devno = 1,
        .input_mode = INPUT_MODE_CMOS,
        .data_rate = MIPI_DATA_RATE_X1,
        .img_rect = {0, 0, 400, 400},
        {.mipi_attr =
             {
                 DATA_TYPE_RAW_10BIT,
                 HI_MIPI_WDR_MODE_NONE,
                 {0, -1, -1, -1}
             }
         }
    };

//=======================================================================================================
// 结构体赋值 OV426 VI_DEV属性
//=======================================================================================================
VI_DEV_ATTR_S DEV_ATTR_OV426_4M_BASE =
    {
        VI_MODE_DIGITAL_CAMERA,
        VI_WORK_MODE_1Multiplex,
        {0x0FFC0000, 0x0},
        VI_SCAN_PROGRESSIVE,
        {-1, -1, -1, -1},
        VI_DATA_SEQ_YUYV,
        {/*port_vsync   port_vsync_neg     port_hsync        port_hsync_neg        */
         VI_VSYNC_FIELD,
         VI_VSYNC_NEG_HIGH,
         VI_HSYNC_VALID_SINGNAL,
         VI_HSYNC_NEG_HIGH,
         VI_VSYNC_VALID_SINGAL,
         VI_VSYNC_VALID_NEG_HIGH,
         /*hsync_hfb    hsync_act    hsync_hhb*/
         {0, 400, 0,
          /*vsync0_vhb vsync0_act vsync0_hhb*/
          0, 400, 0,
          /*vsync1_vhb vsync1_act vsync1_hhb*/
          0, 0, 0}},
        VI_DATA_TYPE_RGB,
        HI_FALSE,
        {400, 400},
        {{
             {400, 400},
         },
         {VI_REPHASE_MODE_NONE,
          VI_REPHASE_MODE_NONE}},
        {WDR_MODE_NONE,
         400},
        DATA_RATE_X1};
//=======================================================================================================
// 结构体变量赋值    OV426输入 VI_PIPE_ATTR_S
//=======================================================================================================
static VI_PIPE_ATTR_S PIPE_ATTR_400x400_RAW10_420_3DNR_RFR =
    {
        VI_PIPE_BYPASS_NONE, HI_FALSE, HI_FALSE, 400, 400, PIXEL_FORMAT_RGB_BAYER_10BPP, COMPRESS_MODE_LINE, DATA_BITWIDTH_10, HI_TRUE, {PIXEL_FORMAT_RGB_BAYER_10BPP, DATA_BITWIDTH_10, VI_NR_REF_FROM_RFR, COMPRESS_MODE_NONE}, HI_FALSE, {-1, -1}};

//=======================================================================================================
// OV426 VI_CHN_ATTR
//=======================================================================================================
static VI_CHN_ATTR_S CHN_ATTR_400x400_420_SDR8_LINEAR =
    {
        {400, 400},
        PIXEL_FORMAT_RGB_BAYER_10BPP,
        DYNAMIC_RANGE_SDR8,
        VIDEO_FORMAT_LINEAR,
        COMPRESS_MODE_NONE,
        1,
        0,
        0,
        {-1, -1}
    };

//=======================================================================================================
// OV426 ISP_PUB_ATTR_S
//=======================================================================================================
ISP_PUB_ATTR_S ISP_PUB_ATTR_OV426_MIPI_4M_30FPS =
    {
        {0, 0, 400, 400},
        {400, 400},
        30.0,
        BAYER_BGGR,
        WDR_MODE_NONE, // WDR_MODE_2To1_FRAME, wdr
        0,
};


//=======================================================================================================
/*=============================== mipi 10 inch 1280x800 lcd config ====================================*/
//=======================================================================================================
/***              //A83T      DEMO      //HISI
    #define HBP     60        60        58
    #define HPW     8         8         8
    #define HFP     52        60        45
    #define VBP     7         7         3
    #define VPW     5         10        2
    #define VFP     5         5         7
***/
//=======================================================================================================
combo_dev_cfg_t *g_mipi_tx_config;
VO_USER_INTFSYNC_INFO_S *g_mipi_tx_user_intfsync_info;
VO_SYNC_INFO_S *g_mipi_tx_sync_info;
lcd_resoluton_t *g_mipi_tx_lcd_resolution;
HI_VOID(*g_mipi_lcd_init)
(HI_S32 s32fd);
#define HBP 20
#define HPW 165
#define HFP 64
#define VBP 2
#define VPW 100
#define VFP 40

    //此函数未使用
    combo_dev_cfg_t MIPI_TX_10INCH_1280x800_60_CONFIG =
        {
            .devno = 0,
            .lane_id = {0, 1, 2, 3},
            .output_mode = OUTPUT_MODE_DSI_VIDEO,
            .output_format = OUT_FORMAT_RGB_24_BIT,
            .video_mode = BURST_MODE,
            .sync_info = {
                .vid_pkt_size = 0,     //
                .vid_hsa_pixels = 0,   // 3,
                .vid_hbp_pixels = 0,   // 2,
                .vid_hline_pixels = 0, // 1349,
                .vid_vsa_lines = 0,    // 1,   // vsa
                .vid_vbp_lines = 0,    // 1,  // vbp
                .vid_vfp_lines = 0,    // 40,   // vfp
                .vid_active_lines = 0, // 842,// vact
                .edpi_cmd_size = 0,
            },
            .phy_data_rate = 3, // 409,
            .pixel_clk = 1,     // 68152,
    };

    //此函数未使用
    combo_dev_cfg_t MIPI_TX_10INCH_1280x800_60_CONFIG_NORMAL =
        {
            .devno = 0,
            .lane_id = {0, 1, 2, 3},
            .output_mode = OUTPUT_MODE_DSI_VIDEO,
            .output_format = OUT_FORMAT_RGB_24_BIT,
            .video_mode = BURST_MODE,
            .sync_info = {
                .vid_pkt_size = 0,     //
                .vid_hsa_pixels = 0,   // 3,
                .vid_hbp_pixels = 0,   // 2,
                .vid_hline_pixels = 0, // 1349,
                .vid_vsa_lines = 0,    // 1,   // vsa
                .vid_vbp_lines = 0,    // 1,  // vbp
                .vid_vfp_lines = 0,    // 40,   // vfp
                .vid_active_lines = 0, // 842,// vact
                .edpi_cmd_size = 0,
            },
            .phy_data_rate = 5, // 409,
            .pixel_clk = 1,     // 68152,
    };

    //============================================================================================
    //使用的此函数
    combo_dev_cfg_t MIPI_TX_10INCH_1280x800_60_CONFIG_VIDEO = // mipi屏幕设置
        {
            .devno = 0,
            .lane_id = {0, 1, 2, 3}, // 4lane，2lane为{0，1，-1，-1}
            .output_mode = OUTPUT_MODE_DSI_VIDEO,
            .output_format = OUT_FORMAT_RGB_24_BIT, // RGB888
            .video_mode = BURST_MODE,
            .sync_info = {
                //时序设置，参数由计算器给出
                .vid_pkt_size = 1280,                       //
                .vid_hsa_pixels = HPW,                      // 3,
                .vid_hbp_pixels = HBP,                      // 2,
                .vid_hline_pixels = 1280 + HPW + HBP + HFP, // 1349,
                .vid_vsa_lines = VPW,                       // 1,   // vsa
                .vid_vbp_lines = VBP,                       // 1,  // vbp
                .vid_vfp_lines = VFP,                       // 40,   // vfp
                .vid_active_lines = 800,                    // 842,// vact
                .edpi_cmd_size = 0,
            },
            .phy_data_rate = 519, // 409,
            .pixel_clk = 86420,   // 68152,像素时钟
    };

    //============================================================================================
    //分频信息 PLL
    VO_USER_INTFSYNC_INFO_S MIPI_TX_10INCH_1280x800_60_USER_INTFSYNC_INFO = //分频信息
        {
            .stUserIntfSyncAttr =
                {
                    .stUserSyncPll =
                        {
                            .u32Fbdiv = 86,      // 68,
                            .u32Frac = 0x6b48d3, // 0x26C764,
                            .u32Refdiv = 2,
                            .u32Postdiv1 = 4,
                            .u32Postdiv2 = 3,
                        },
                },
            .u32DevDiv = 1,
            .u32PreDiv = 1,
    };
    VO_SYNC_INFO_S MIPI_TX_10INCH_1280x800_60_SYNC_INFO =
        {
            .bSynm = 0,
            .bIop = 1,
            .u8Intfb = 0,
            .u16Bvact = 1,
            .u16Bvbb = 1,
            .u16Bvfb = 1,
            .u16Hmid = 1,
            .bIdv = 0,
            .bIhs = 0,
            .bIvs = 0,

            .u16Hact = 1280,
            .u16Hbb = HBP + HPW, // 5,////////////////
            .u16Hfb = HFP,       // 64,
            .u16Hpw = HPW,       // 2,
            .u16Vact = 800,
            .u16Vbb = VPW + VBP, // 2,
            .u16Vfb = VFP,       // 40,
            .u16Vpw = VPW,       // 4,
    };

    //============================================================================================
    //长宽和帧率设置
    lcd_resoluton_t MIPI_TX_10INCH_1280x800_60_LCD_RESOLUTION =
        {
            .pu32W = 1280,
            .pu32H = 800,
            .pu32Frm = 60,
    };

    //============================================================================================
    // mipi屏初始化命令发送函数
    int fd_dsi2lvds = 0;
    int dsi2lvds_i2c_write(int addr, int data)
    {
        int idx = 0;
        int ret;
        char buf[8];
        buf[idx] = (addr >> 8) & 0xff;
        idx++;
        buf[idx] = addr & 0xff;
        idx++;
        buf[idx] = data & 0xff;
        ret = write(fd_dsi2lvds, buf, 3);
        if (ret < 0)
        {
            printf("I2C_WRITE DATA error! addr:%x\n", addr);
        }
        return 0;
    }

    //============================================================================================
    // mipi-dsi转LVDS
    int dsi2lvds_i2c_read(int addr, int data)
    {
        int idx = 0;
        char buf[8];
        buf[idx] = (addr >> 8) & 0xff;
        idx++;
        buf[idx] = addr & 0xff;
        idx++;
        write(fd_dsi2lvds, buf, 2);
        read(fd_dsi2lvds, buf, 1);
        return buf[0];
    }

    //============================================================================================
    // 10寸屏初始化序列
    HI_VOID InitScreen_mipi_10inch_1280x800(HI_S32 s32fd)
    {
        HI_S32 fd = s32fd;
        char args[60];
        int fd1;
        fd1 = open("/etc/backlight", O_RDWR);
        if (fd1 > 0)
        {
            read(fd1, args, 45);
            system(args);
            close(fd1);
        }
        else
        {
            system("/usr/tools/pwm_write 1 180 0xff 1 >/dev/null");
            // sprintf(args,"/usr/tools/pwm_write 1 %d 0xff 1 %d >/dev/null");
        }
        // GPIO6_7 PWM_OUT1_LCD CLK=3M
        // system("himm 0x111F0028 0xF1 >/dev/null");
        // system("himm 0x12070020 255	 >/dev/null");//#500_000 DUTY
        // system(args);//#400_000 HIGH
        // system("himm 0x12070028 0xFF >/dev/null");
        // system("himm 0x1207002C 0x05 >/dev/null");
        // GPIO2_2 USB_PWR_3V3
        // system("himm 0x10FF0044 0xF0 >/dev/null");
        // system("himm 0x120D2400 0x04 >/dev/null");
        // system("himm 0x120D2010 0x04 >/dev/null");

        system("himm 0x112F0034 0xF0 >/dev/null"); // 0_6
        system("himm 0x112F009C 0xF0 >/dev/null"); // 0_5

        system("himm 0x120D0400 0x60 >/dev/null"); // 0
        system("himm 0x120D0080 0x00 >/dev/null"); // 0X20
        usleep(20000);
        // GPIO8_3 LVDS_STBY  ->>>>STBY = 0
        system("himm 0x112f0028 0xf4 >/dev/null");
        system("himm 0x120D8400 0x05 >/dev/null");
        system("himm 0x120D8010 0x00 >/dev/null"); // 0X08
        usleep(20000);
        // GPIO0_6 MIPI_PWR_EN ->>>>VDD-CORE = 0
        system("himm 0x120D0400 0x60 >/dev/null");
        system("himm 0x120D0100 0x00 >/dev/null"); // 0X40

        usleep(10000);
        // VDD-CORE = 1
        system("himm 0x120D0100 0x40 >/dev/null");
        usleep(10000);
        // STBY = 1
        system("himm 0x120D8010 0x04 >/dev/null");
        usleep(10000);
        // RESX = 1
        system("himm 0x120D0080 0x20 >/dev/null");
        ioctl(fd, HI_MIPI_TX_SET_DEV_CFG, &MIPI_TX_10INCH_1280x800_60_CONFIG_NORMAL);
        // ioctl(fd, HI_MIPI_TX_SET_DEV_CFG, &MIPI_TX_10INCH_1280x800_60_CONFIG_VIDEO);
        ioctl(fd, HI_MIPI_TX_ENABLE);
        fd_dsi2lvds = open("/dev/i2c-1", O_RDWR, S_IRUSR | S_IWUSR); //以下为屏幕初始化命令
        ioctl(fd_dsi2lvds, 0x0706, 0x0f);
        dsi2lvds_i2c_write(0x013c, 0x05);
        dsi2lvds_i2c_write(0x013d, 0x00);
        dsi2lvds_i2c_write(0x013e, 0x03);
        dsi2lvds_i2c_write(0x013f, 0x00);

        dsi2lvds_i2c_write(0x0114, 0x03); // 0x08
        dsi2lvds_i2c_write(0x0115, 0x00);
        dsi2lvds_i2c_write(0x0116, 0x00);
        dsi2lvds_i2c_write(0x0117, 0x00);

        dsi2lvds_i2c_write(0x0164, 0x02);
        dsi2lvds_i2c_write(0x0165, 0x00);
        dsi2lvds_i2c_write(0x0166, 0x00);
        dsi2lvds_i2c_write(0x0167, 0x00);

        dsi2lvds_i2c_write(0x0168, 0x02);
        dsi2lvds_i2c_write(0x0169, 0x00);
        dsi2lvds_i2c_write(0x016a, 0x00);
        dsi2lvds_i2c_write(0x016b, 0x00);

        dsi2lvds_i2c_write(0x016c, 0x02);
        dsi2lvds_i2c_write(0x016d, 0x00);
        dsi2lvds_i2c_write(0x016e, 0x00);
        dsi2lvds_i2c_write(0x016f, 0x00);

        dsi2lvds_i2c_write(0x0170, 0x02);
        dsi2lvds_i2c_write(0x0171, 0x00);
        dsi2lvds_i2c_write(0x0172, 0x00);
        dsi2lvds_i2c_write(0x0173, 0x00);
        dsi2lvds_i2c_write(0x0134, 0x1f);
        dsi2lvds_i2c_write(0x0135, 0x00);
        dsi2lvds_i2c_write(0x0136, 0x00);
        dsi2lvds_i2c_write(0x0137, 0x00);

        dsi2lvds_i2c_write(0x0210, 0x1f);
        dsi2lvds_i2c_write(0x0211, 0x00);
        dsi2lvds_i2c_write(0x0212, 0x00);
        dsi2lvds_i2c_write(0x0213, 0x00);

        dsi2lvds_i2c_write(0x0104, 0x01);
        dsi2lvds_i2c_write(0x0105, 0x00);
        dsi2lvds_i2c_write(0x0106, 0x00);
        dsi2lvds_i2c_write(0x0107, 0x00);

        dsi2lvds_i2c_write(0x0204, 0x01);
        dsi2lvds_i2c_write(0x0205, 0x00);
        dsi2lvds_i2c_write(0x0206, 0x00);
        dsi2lvds_i2c_write(0x0207, 0x00);

        dsi2lvds_i2c_write(0x0450, 0x20);
        dsi2lvds_i2c_write(0x0451, 0x01);
        dsi2lvds_i2c_write(0x0452, 0xF0);
        dsi2lvds_i2c_write(0x0453, 0x03);

        dsi2lvds_i2c_write(0x0454, HPW); // hpw  2
        dsi2lvds_i2c_write(0x0455, 0);
        dsi2lvds_i2c_write(0x0456, HBP); // hbp 3
        dsi2lvds_i2c_write(0x0457, 0);

        dsi2lvds_i2c_write(0x0458, 0x00);
        dsi2lvds_i2c_write(0x0459, 0x05);
        dsi2lvds_i2c_write(0x045a, HFP);  // 0X40
        dsi2lvds_i2c_write(0x045b, 0x00); //

        dsi2lvds_i2c_write(0x045c, VPW);  // 1
        dsi2lvds_i2c_write(0x045d, 0x00); // vpw
        dsi2lvds_i2c_write(0x045e, VBP);  // 1
        dsi2lvds_i2c_write(0x045f, 0x00); //

        dsi2lvds_i2c_write(0x0460, 0x20);
        dsi2lvds_i2c_write(0x0461, 0x03);
        dsi2lvds_i2c_write(0x0462, VFP);  // 0X28
        dsi2lvds_i2c_write(0x0463, 0x00); // vfp

        dsi2lvds_i2c_write(0x0464, 0x01);
        dsi2lvds_i2c_write(0x0465, 0x00);
        dsi2lvds_i2c_write(0x0466, 0x00);
        dsi2lvds_i2c_write(0x0467, 0x00);

        dsi2lvds_i2c_write(0x04a0, 0x06);
        dsi2lvds_i2c_write(0x04a1, 0x80);
        dsi2lvds_i2c_write(0x04a2, 0x44);
        dsi2lvds_i2c_write(0x04a3, 0x00);
        usleep(500);
        dsi2lvds_i2c_write(0x04a0, 0x06);
        dsi2lvds_i2c_write(0x04a1, 0x80);
        dsi2lvds_i2c_write(0x04a2, 0x04);
        dsi2lvds_i2c_write(0x04a3, 0x00);

        dsi2lvds_i2c_write(0x0504, 0x04);
        dsi2lvds_i2c_write(0x0505, 0x00);
        dsi2lvds_i2c_write(0x0506, 0x00);
        dsi2lvds_i2c_write(0x0507, 0x00);

        dsi2lvds_i2c_write(0x0480, 0x00);
        dsi2lvds_i2c_write(0x0481, 0x01);
        dsi2lvds_i2c_write(0x0482, 0x02);
        dsi2lvds_i2c_write(0x0483, 0x03);

        dsi2lvds_i2c_write(0x0484, 0x04);
        dsi2lvds_i2c_write(0x0485, 0x07);
        dsi2lvds_i2c_write(0x0486, 0x05);
        dsi2lvds_i2c_write(0x0487, 0x08);

        dsi2lvds_i2c_write(0x0488, 0x09);
        dsi2lvds_i2c_write(0x0489, 0x0a);
        dsi2lvds_i2c_write(0x048a, 0x0e);
        dsi2lvds_i2c_write(0x048b, 0x0f);

        dsi2lvds_i2c_write(0x048c, 0x0b);
        dsi2lvds_i2c_write(0x048d, 0x0c);
        dsi2lvds_i2c_write(0x048e, 0x0d);
        dsi2lvds_i2c_write(0x048f, 0x10);

        dsi2lvds_i2c_write(0x0490, 0x16);
        dsi2lvds_i2c_write(0x0491, 0x17);
        dsi2lvds_i2c_write(0x0492, 0x11);
        dsi2lvds_i2c_write(0x0493, 0x12);

        dsi2lvds_i2c_write(0x0494, 0x13);
        dsi2lvds_i2c_write(0x0495, 0x14);
        dsi2lvds_i2c_write(0x0496, 0x15);
        dsi2lvds_i2c_write(0x0497, 0x1b);

        dsi2lvds_i2c_write(0x0498, 0x18);
        dsi2lvds_i2c_write(0x0499, 0x19);
        dsi2lvds_i2c_write(0x049a, 0x1a);
        dsi2lvds_i2c_write(0x049b, 0x06);

        dsi2lvds_i2c_write(0x049c, 0x31);
        dsi2lvds_i2c_write(0x049d, 0x00);
        dsi2lvds_i2c_write(0x049e, 0x00);
        dsi2lvds_i2c_write(0x049f, 0x00);

        ioctl(fd, HI_MIPI_TX_SET_DEV_CFG, g_mipi_tx_config);
        ioctl(fd, HI_MIPI_TX_ENABLE);
    }









//============================================================================================
// VI 摄像头设备设置
//============================================================================================
HI_S32 SAMPLE_COMM_VI_StartDev(SAMPLE_VI_INFO_S *pstViInfo)
{
    VI_DEV_ATTR_S stViDevAttr;
    printf("VI input camera mode:%d \n", pstViInfo->stSnsInfo.enSnsType);
    switch (pstViInfo->stSnsInfo.enSnsType)
    {
    case OS01A: hi_memcpy(&stViDevAttr, sizeof(VI_DEV_ATTR_S), &DEV_ATTR_OS01A_4M_BASE, sizeof(VI_DEV_ATTR_S));break;
    case OV426: hi_memcpy(&stViDevAttr, sizeof(VI_DEV_ATTR_S), &DEV_ATTR_OV426_4M_BASE, sizeof(VI_DEV_ATTR_S));break;
    case OV9734:hi_memcpy(&stViDevAttr, sizeof(VI_DEV_ATTR_S), &DEV_ATTR_OV9734_4M_BASE, sizeof(VI_DEV_ATTR_S));break;
    default:hi_memcpy(&stViDevAttr, sizeof(VI_DEV_ATTR_S), &DEV_ATTR_OV426_4M_BASE, sizeof(VI_DEV_ATTR_S));break;
    }
    stViDevAttr.stWDRAttr.enWDRMode = pstViInfo->stDevInfo.enWDRMode;
    if(VI_PARALLEL_VPSS_OFFLINE == pstViInfo->stPipeInfo.enMastPipeMode || VI_PARALLEL_VPSS_PARALLEL == pstViInfo->stPipeInfo.enMastPipeMode)
    {
        stViDevAttr.enDataRate = DATA_RATE_X2;
    }
    CHECK_RET(HI_MPI_VI_SetDevAttr(pstViInfo->stDevInfo.ViDev, &stViDevAttr), "HI_MPI_VI_SetDevAttr()");
    CHECK_RET(HI_MPI_VI_EnableDev(pstViInfo->stDevInfo.ViDev), "HI_MPI_VI_EnableDev()");
    return HI_SUCCESS;
}

//============================================================================================
//停止VI设备
//============================================================================================
HI_S32 SAMPLE_COMM_VI_StopDev(SAMPLE_VI_INFO_S *pstViInfo)
{
    CHECK_RET(HI_MPI_VI_DisableDev(pstViInfo->stDevInfo.ViDev), "HI_MPI_VI_DisableDev()");
    return HI_SUCCESS;
}

//============================================================================================
//设备绑定VI-pipe
//============================================================================================
HI_S32 SAMPLE_COMM_VI_BindPipeDev(SAMPLE_VI_INFO_S *pstViInfo)
{
    HI_S32 i;
    HI_S32 s32PipeCnt = 0;
    VI_DEV_BIND_PIPE_S stDevBindPipe = {0};
    for (i = 0; i < 4; i++)
    {
        if (pstViInfo->stPipeInfo.aPipe[i] >= 0 && pstViInfo->stPipeInfo.aPipe[i] < VI_MAX_PIPE_NUM)
        {
            stDevBindPipe.PipeId[s32PipeCnt] = pstViInfo->stPipeInfo.aPipe[i];
            s32PipeCnt++;
            stDevBindPipe.u32Num = s32PipeCnt;
        }
    }
    CHECK_RET(HI_MPI_VI_SetDevBindPipe(pstViInfo->stDevInfo.ViDev, &stDevBindPipe), "HI_MPI_VI_SetDevBindPipe()");
    return HI_SUCCESS;
}

//============================================================================================
//关闭单个VI-pipe
//============================================================================================
static HI_S32 SAMPLE_COMM_VI_StopSingleViPipe(VI_PIPE ViPipe)
{
    CHECK_RET(HI_MPI_VI_StopPipe(ViPipe), "HI_MPI_VI_StopPipe()");
    CHECK_RET(HI_MPI_VI_DestroyPipe(ViPipe), "HI_MPI_VI_DestroyPipe()");
    return HI_SUCCESS;
}

//============================================================================================
//开启VI-pipe
//============================================================================================
HI_S32 SAMPLE_COMM_VI_StartViPipe(SAMPLE_VI_INFO_S *pstViInfo)
{
    HI_S32 i, j;
    HI_S32 s32Ret = HI_SUCCESS;
    VI_PIPE ViPipe;
    VI_PIPE_ATTR_S stPipeAttr;
    for (i = 0; i < WDR_MAX_PIPE_NUM; i++)
    {
        if (pstViInfo->stPipeInfo.aPipe[i] >= 0 && pstViInfo->stPipeInfo.aPipe[i] < VI_MAX_PIPE_NUM)
        {
            ViPipe = pstViInfo->stPipeInfo.aPipe[i];
            switch (pstViInfo->stSnsInfo.enSnsType)
            {
            case OS01A:hi_memcpy(&stPipeAttr, sizeof(VI_PIPE_ATTR_S), &PIPE_ATTR_800x800_RAW12_420_3DNR_RFR, sizeof(VI_PIPE_ATTR_S));break;
            case OV426:hi_memcpy(&stPipeAttr, sizeof(VI_PIPE_ATTR_S), &PIPE_ATTR_400x400_RAW10_420_3DNR_RFR, sizeof(VI_PIPE_ATTR_S));break;
            case OV9734:hi_memcpy(&stPipeAttr, sizeof(VI_PIPE_ATTR_S), &PIPE_ATTR_720x720_RAW12_420_3DNR_RFR, sizeof(VI_PIPE_ATTR_S));break;
            default: break;
            }
            if (HI_TRUE == pstViInfo->stPipeInfo.bIspBypass)
            {
                stPipeAttr.bIspBypass = HI_TRUE;
                stPipeAttr.enPixFmt = pstViInfo->stPipeInfo.enPixFmt;
                stPipeAttr.enBitWidth = DATA_BITWIDTH_8;
            }
            if ((2 == ViPipe) || (3 == ViPipe))
                stPipeAttr.enCompressMode = COMPRESS_MODE_NONE;
            if ((pstViInfo->stSnapInfo.bSnap) && (pstViInfo->stSnapInfo.bDoublePipe) && (ViPipe == pstViInfo->stSnapInfo.SnapPipe))
            {
                s32Ret = HI_MPI_VI_CreatePipe(ViPipe, &stPipeAttr);
                if (s32Ret != HI_SUCCESS)
                    goto EXIT;
            }
            else
            {
                s32Ret = HI_MPI_VI_CreatePipe(ViPipe, &stPipeAttr);
                if (s32Ret != HI_SUCCESS)
                    return HI_FAILURE;
                s32Ret = HI_MPI_VI_SetPipeVCNumber(ViPipe, pstViInfo->stPipeInfo.u32VCNum[i]);
                if (s32Ret != HI_SUCCESS)
                {
                    HI_MPI_VI_DestroyPipe(ViPipe);
                    SAMPLE_PRT("HI_MPI_VI_SetPipeVCNumber failed with %#x!\n", s32Ret);
                    return HI_FAILURE;
                }
                s32Ret = HI_MPI_VI_StartPipe(ViPipe);
                if (s32Ret != HI_SUCCESS)
                {
                    HI_MPI_VI_DestroyPipe(ViPipe);
                    SAMPLE_PRT("HI_MPI_VI_StartPipe failed with %#x!\n", s32Ret);
                    return HI_FAILURE;
                }
            }
        }
    }
    return s32Ret;
EXIT:
    for (j = 0; j < i; j++)
    {
        ViPipe = j;
        SAMPLE_COMM_VI_StopSingleViPipe(ViPipe);
    }
    return s32Ret;
}


//============================================================================================
//关闭全部VI-pipe
//============================================================================================
HI_S32 SAMPLE_COMM_VI_StopViPipe(SAMPLE_VI_INFO_S *pstViInfo)
{
    HI_S32 i;
    VI_PIPE ViPipe;
    for (i = 0; i < WDR_MAX_PIPE_NUM; i++)
    {
        if (pstViInfo->stPipeInfo.aPipe[i] >= 0 && pstViInfo->stPipeInfo.aPipe[i] < VI_MAX_PIPE_NUM)
        {
            ViPipe = pstViInfo->stPipeInfo.aPipe[i];
            SAMPLE_COMM_VI_StopSingleViPipe(ViPipe);
        }
    }
    return HI_SUCCESS;
}

//============================================================================================
//配置并启动通道 VI-CHN
//============================================================================================
HI_S32 SAMPLE_COMM_VI_StartViChn(SAMPLE_VI_INFO_S *pstViInfo)
{
    HI_S32 i;
    HI_BOOL bNeedChn;
    HI_S32 s32Ret = HI_SUCCESS;
    VI_PIPE ViPipe;
    VI_CHN ViChn;
    VI_CHN_ATTR_S stChnAttr;
    VI_VPSS_MODE_E enMastPipeMode;
    for (i = 0; i < WDR_MAX_PIPE_NUM; i++)
    {
        if (pstViInfo->stPipeInfo.aPipe[i] >= 0 && pstViInfo->stPipeInfo.aPipe[i] < VI_MAX_PIPE_NUM)
        {
            ViPipe = pstViInfo->stPipeInfo.aPipe[i];
            ViChn = pstViInfo->stChnInfo.ViChn;
            switch (pstViInfo->stSnsInfo.enSnsType)
            {
            case OS01A: hi_memcpy(&stChnAttr, sizeof(VI_CHN_ATTR_S), &CHN_ATTR_800x800_420_SDR8_LINEAR, sizeof(VI_CHN_ATTR_S)); break;
            case OV426: hi_memcpy(&stChnAttr, sizeof(VI_CHN_ATTR_S), &CHN_ATTR_400x400_420_SDR8_LINEAR, sizeof(VI_CHN_ATTR_S)); break;
            case OV9734: hi_memcpy(&stChnAttr, sizeof(VI_CHN_ATTR_S), &CHN_ATTR_720x720_420_SDR8_LINEAR, sizeof(VI_CHN_ATTR_S)); break;
            default: break;
            }
            stChnAttr.enDynamicRange = pstViInfo->stChnInfo.enDynamicRange;
            stChnAttr.enVideoFormat = pstViInfo->stChnInfo.enVideoFormat;
            stChnAttr.enPixelFormat = pstViInfo->stChnInfo.enPixFormat;
            stChnAttr.enCompressMode = pstViInfo->stChnInfo.enCompressMode;
            if (WDR_MODE_NONE == pstViInfo->stDevInfo.enWDRMode)
                bNeedChn = HI_TRUE;
            else
                bNeedChn = (i > 0) ? HI_FALSE : HI_TRUE;
            if (bNeedChn)
            {
                s32Ret = HI_MPI_VI_SetChnAttr(ViPipe, ViChn, &stChnAttr);
                if (s32Ret != HI_SUCCESS)
                    return HI_FAILURE;
                enMastPipeMode = pstViInfo->stPipeInfo.enMastPipeMode;
                if (VI_OFFLINE_VPSS_OFFLINE == enMastPipeMode || VI_ONLINE_VPSS_OFFLINE == enMastPipeMode || VI_PARALLEL_VPSS_OFFLINE == enMastPipeMode)
                {
                    s32Ret = HI_MPI_VI_EnableChn(ViPipe, ViChn);
                    if (s32Ret != HI_SUCCESS)
                        return HI_FAILURE;
                }
            }
        }
    }
    return s32Ret;
}


//============================================================================================
//停止VI-CHN通道
//============================================================================================
HI_S32 SAMPLE_COMM_VI_StopViChn(SAMPLE_VI_INFO_S *pstViInfo)
{
    HI_S32 i;
    HI_BOOL bNeedChn;
    HI_S32 s32Ret = HI_SUCCESS;
    VI_PIPE ViPipe;
    VI_CHN ViChn;
    VI_VPSS_MODE_E enMastPipeMode;
    for (i = 0; i < 4; i++)
    {
        if (pstViInfo->stPipeInfo.aPipe[i] >= 0 && pstViInfo->stPipeInfo.aPipe[i] < VI_MAX_PIPE_NUM)
        {
            ViPipe = pstViInfo->stPipeInfo.aPipe[i];
            ViChn = pstViInfo->stChnInfo.ViChn;
            if (WDR_MODE_NONE == pstViInfo->stDevInfo.enWDRMode)
                bNeedChn = HI_TRUE;
            else
                bNeedChn = (i > 0) ? HI_FALSE : HI_TRUE;
            if (bNeedChn)
            {
                enMastPipeMode = pstViInfo->stPipeInfo.enMastPipeMode;
                if (VI_OFFLINE_VPSS_OFFLINE == enMastPipeMode || VI_ONLINE_VPSS_OFFLINE == enMastPipeMode || VI_PARALLEL_VPSS_OFFLINE == enMastPipeMode)
                {
                    s32Ret = HI_MPI_VI_DisableChn(ViPipe, ViChn);
                    return HI_FAILURE;
                }
            }
        }
    }
    return s32Ret;
}

//============================================================================================
// ISP 提供的 sensor 注册的回调接口;   注册sensor库
//============================================================================================
HI_S32 SAMPLE_COMM_ISP_Sensor_Regiter_callback(ISP_DEV IspDev, HI_U32 u32SnsId)
{
    ALG_LIB_S stAeLib;
    ALG_LIB_S stAwbLib;
    const ISP_SNS_OBJ_S *pstSnsObj;
    HI_S32 s32Ret = -1;
    if (MAX_SENSOR_NUM <= u32SnsId)
    {
        SAMPLE_PRT("invalid sensor id: %d\n", u32SnsId);
        return HI_FAILURE;
    }
    switch (g_enSnsType[u32SnsId])
    {
    case OS01A: pstSnsObj = &stSnsOs01aObj; break;
    case OV426: pstSnsObj = &stSnsOv426Obj; break;
    case OV9734: pstSnsObj = &stSnsov9734Obj; break;
    default: pstSnsObj = &stSnsOv426Obj; break;
    }
    stAeLib.s32Id = IspDev;
    stAwbLib.s32Id = IspDev;
    strncpy(stAeLib.acLibName, HI_AE_LIB_NAME, sizeof(HI_AE_LIB_NAME));
    strncpy(stAwbLib.acLibName, HI_AWB_LIB_NAME, sizeof(HI_AWB_LIB_NAME));
    //  strncpy(stAfLib.acLibName, HI_AF_LIB_NAME, sizeof(HI_AF_LIB_NAME));
    if (pstSnsObj->pfnRegisterCallback != HI_NULL)
    {
        s32Ret = pstSnsObj->pfnRegisterCallback(IspDev, &stAeLib, &stAwbLib);
        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("sensor_register_callback failed with %#x!\n", s32Ret);
            return s32Ret;
        }
    }
    else
    {
        SAMPLE_PRT("sensor_register_callback failed with HI_NULL!\n");
    }
    g_au32IspSnsId[IspDev] = u32SnsId;
    return HI_SUCCESS;
}

//============================================================================================
// ISP 提供的 sensor 反注册的回调接口。
//============================================================================================
HI_S32 SAMPLE_COMM_ISP_Sensor_UnRegiter_callback(ISP_DEV IspDev)
{
    ALG_LIB_S stAeLib;
    ALG_LIB_S stAwbLib;
    HI_U32 u32SnsId;
    const ISP_SNS_OBJ_S *pstSnsObj;
    HI_S32 s32Ret = -1;
    u32SnsId = g_au32IspSnsId[IspDev];
    if (MAX_SENSOR_NUM <= u32SnsId)
        return HI_FAILURE;
    switch (g_enSnsType[u32SnsId])
    {
    case OS01A: pstSnsObj = &stSnsOs01aObj; break;
    case OV426: pstSnsObj = &stSnsOv426Obj; break;
    case OV9734: pstSnsObj = &stSnsov9734Obj; break;
    default: pstSnsObj = &stSnsOv426Obj; break;
    }
    stAeLib.s32Id = IspDev;
    stAwbLib.s32Id = IspDev;
    strncpy(stAeLib.acLibName, HI_AE_LIB_NAME, sizeof(HI_AE_LIB_NAME));
    strncpy(stAwbLib.acLibName, HI_AWB_LIB_NAME, sizeof(HI_AWB_LIB_NAME));
    if (pstSnsObj->pfnUnRegisterCallback != HI_NULL)
    {
        s32Ret = pstSnsObj->pfnUnRegisterCallback(IspDev, &stAeLib, &stAwbLib);
        return s32Ret;
    }
    return HI_SUCCESS;
}

//============================================================================================
// ISP 提供的 AE 库注册的回调接口
//============================================================================================
HI_S32 SAMPLE_COMM_ISP_Aelib_Callback(ISP_DEV IspDev)
{
    ALG_LIB_S stAeLib;
    stAeLib.s32Id = IspDev;
    strncpy(stAeLib.acLibName, HI_AE_LIB_NAME, sizeof(HI_AE_LIB_NAME));
    CHECK_RET(HI_MPI_AE_Register(IspDev, &stAeLib), "aelib register call back");
    return HI_SUCCESS;
}

//============================================================================================
// ISP 提供的 AE 库反注册的回调接口
//============================================================================================
HI_S32 SAMPLE_COMM_ISP_Aelib_UnCallback(ISP_DEV IspDev)
{
    ALG_LIB_S stAeLib;
    stAeLib.s32Id = IspDev;
    strncpy(stAeLib.acLibName, HI_AE_LIB_NAME, sizeof(HI_AE_LIB_NAME));
    CHECK_RET(HI_MPI_AE_UnRegister(IspDev, &stAeLib), "aelib unregister call back");
    return HI_SUCCESS;
}

//============================================================================================
// ISP 提供的 AWB 库注册的回调接口
//============================================================================================
HI_S32 SAMPLE_COMM_ISP_Awblib_Callback(ISP_DEV IspDev)
{
    ALG_LIB_S stAwbLib;
    stAwbLib.s32Id = IspDev;
    strncpy(stAwbLib.acLibName, HI_AWB_LIB_NAME, sizeof(HI_AWB_LIB_NAME));
    CHECK_RET(HI_MPI_AWB_Register(IspDev, &stAwbLib), "awblib register call back");
    return HI_SUCCESS;
}

//============================================================================================
// ISP 提供的 AWB 库反注册的回调接口。
//============================================================================================
HI_S32 SAMPLE_COMM_ISP_Awblib_UnCallback(ISP_DEV IspDev)
{
    ALG_LIB_S stAwbLib;
    stAwbLib.s32Id = IspDev;
    strncpy(stAwbLib.acLibName, HI_AWB_LIB_NAME, sizeof(HI_AWB_LIB_NAME));
    CHECK_RET(HI_MPI_AWB_UnRegister(IspDev, &stAwbLib), "awblib unregister call back");
    return HI_SUCCESS;
}

//============================================================================================
// ISP关联摄像头的库文件
//============================================================================================
HI_S32 SAMPLE_COMM_ISP_BindSns(ISP_DEV IspDev, HI_U32 u32SnsId, SAMPLE_SNS_TYPE_E enSnsType, HI_S8 s8SnsDev)
{
    ISP_SNS_COMMBUS_U uSnsBusInfo;
    const ISP_SNS_OBJ_S *pstSnsObj;
    HI_S32 s32Ret;
    if (MAX_SENSOR_NUM <= u32SnsId)
    {
        SAMPLE_PRT("invalid sensor id: %d\n", u32SnsId);
        return HI_FAILURE;
    }
    switch (g_enSnsType[u32SnsId])
    {
    case OS01A: pstSnsObj = &stSnsOs01aObj; break;
    case OV426: pstSnsObj = &stSnsOv426Obj; break;
    case OV9734: pstSnsObj = &stSnsov9734Obj; break;
    default: pstSnsObj = &stSnsOv426Obj; break;
    }
    if (HI_NULL == pstSnsObj)
    {
        SAMPLE_PRT("sensor %d not exist!\n", u32SnsId);
        return HI_FAILURE;
    }
    uSnsBusInfo.s8I2cDev = s8SnsDev;
    if (HI_NULL != pstSnsObj->pfnSetBusInfo)
    {
        s32Ret = pstSnsObj->pfnSetBusInfo(IspDev, uSnsBusInfo);
        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("set sensor bus info failed with %#x!\n", s32Ret);
            return s32Ret;
        }
    }
    else
    {
        SAMPLE_PRT("not support set sensor bus info!\n");
        return HI_FAILURE;
    }
    return s32Ret;
}


//============================================================================================
//关闭ISP
//============================================================================================
HI_VOID SAMPLE_COMM_ISP_Stop(ISP_DEV IspDev)
{
    if (g_IspPid[IspDev])
    {
        HI_MPI_ISP_Exit(IspDev);
        pthread_join(g_IspPid[IspDev], NULL);
        SAMPLE_COMM_ISP_Awblib_UnCallback(IspDev);
        SAMPLE_COMM_ISP_Aelib_UnCallback(IspDev);
        SAMPLE_COMM_ISP_Sensor_UnRegiter_callback(IspDev);
        g_IspPid[IspDev] = 0;
    }
    return;
}

//============================================================================================
//
//============================================================================================
static void *SAMPLE_COMM_ISP_Thread(void *param)
{
    HI_S32 s32Ret;
    ISP_DEV IspDev;
    HI_CHAR szThreadName[20];
    IspDev = (ISP_DEV)param;
    snprintf(szThreadName, 20, "ISP%d_RUN", IspDev);
    prctl(PR_SET_NAME, szThreadName, 0, 0, 0);
    s32Ret = HI_MPI_ISP_Run(IspDev);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_ISP_Run failed with %#x!\n", s32Ret);
    }
    return NULL;
}

//============================================================================================
//运行ISP
//============================================================================================
HI_S32 SAMPLE_COMM_ISP_Run(ISP_DEV IspDev)
{
    HI_S32 s32Ret = 0;
    pthread_attr_t *pstAttr = NULL;
    s32Ret = pthread_create(&g_IspPid[IspDev], pstAttr, SAMPLE_COMM_ISP_Thread, (HI_VOID *)IspDev);
    if (0 != s32Ret)
    {
        SAMPLE_PRT("create isp running thread failed!, error: %d, %s\r\n", s32Ret, strerror(s32Ret));
        goto out;
    }
out:
    if (NULL != pstAttr)
    {
        pthread_attr_destroy(pstAttr);
    }
    return s32Ret;
}

//============================================================================================
//设置MIPI-CSI为高速模式
//============================================================================================
HI_S32 SAMPLE_COMM_VI_SetMipiHsMode(lane_divide_mode_t enHsMode)
{
    HI_S32 fd;
    HI_S32 s32Ret;
    fd = open(MIPI_DEV_NODE, O_RDWR);
    if (fd < 0)
    {
        SAMPLE_PRT("open hi_mipi dev failed\n");
        return -1;
    }
    s32Ret = ioctl(fd, HI_MIPI_SET_HS_MODE, &enHsMode);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MIPI_SET_HS_MODE failed\n");
    }
    close(fd);
    return s32Ret;
}

//============================================================================================
//使能VI  MIPI时钟
//============================================================================================
HI_S32 SAMPLE_COMM_VI_EnableMipiClock(SAMPLE_VI_CONFIG_S *pstViConfig)
{
    HI_S32 i = 0;
    HI_S32 s32ViNum = 0;
    HI_S32 s32Ret = HI_SUCCESS;
    HI_S32 fd;
    combo_dev_t devno = 0;
    SAMPLE_VI_INFO_S *pstViInfo = HI_NULL;
    if (!pstViConfig)
    {
        SAMPLE_PRT("%s: null ptr\n", __FUNCTION__);
        return HI_FAILURE;
    }
    fd = open(MIPI_DEV_NODE, O_RDWR);
    if (fd < 0)
    {
        SAMPLE_PRT("open hi_mipi dev failed\n");
        return HI_FAILURE;
    }
    for (i = 0; i < pstViConfig->s32WorkingViNum; i++)
    {
        s32ViNum = pstViConfig->as32WorkingViId[i];
        pstViInfo = &pstViConfig->astViInfo[s32ViNum];
        devno = pstViInfo->stSnsInfo.MipiDev;
        s32Ret = ioctl(fd, HI_MIPI_ENABLE_MIPI_CLOCK, &devno);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("MIPI_ENABLE_CLOCK %d failed\n", devno);
            goto EXIT;
        }
    }
EXIT:
    close(fd);
    return s32Ret;
}

//============================================================================================
//关闭VI mipi时钟
//============================================================================================
HI_S32 SAMPLE_COMM_VI_DisableMipiClock(SAMPLE_VI_CONFIG_S *pstViConfig)
{
    HI_S32 i = 0;
    HI_S32 s32ViNum = 0;
    HI_S32 s32Ret = HI_SUCCESS;
    HI_S32 fd;
    combo_dev_t devno = 0;
    SAMPLE_VI_INFO_S *pstViInfo = HI_NULL;
    if (!pstViConfig)
    {
        SAMPLE_PRT("%s: null ptr\n", __FUNCTION__);
        return HI_FAILURE;
    }
    fd = open(MIPI_DEV_NODE, O_RDWR);
    if (fd < 0)
    {
        SAMPLE_PRT("open hi_mipi dev failed\n");
        return HI_FAILURE;
    }
    for (i = 0; i < pstViConfig->s32WorkingViNum; i++)
    {
        s32ViNum = pstViConfig->as32WorkingViId[i];
        pstViInfo = &pstViConfig->astViInfo[s32ViNum];
        devno = pstViInfo->stSnsInfo.MipiDev;
        s32Ret = ioctl(fd, HI_MIPI_DISABLE_MIPI_CLOCK, &devno);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("MIPI_DISABLE_CLOCK %d failed\n", devno);
            goto EXIT;
        }
    }
EXIT:
    close(fd);
    return s32Ret;
}

//============================================================================================
//复位VI MIPI-CSI
//============================================================================================
HI_S32 SAMPLE_COMM_VI_ResetMipi(SAMPLE_VI_CONFIG_S *pstViConfig)
{
    HI_S32 i = 0;
    HI_S32 s32ViNum = 0;
    HI_S32 s32Ret = HI_SUCCESS;
    HI_S32 fd;
    combo_dev_t devno = 0;
    SAMPLE_VI_INFO_S *pstViInfo = HI_NULL;
    if (!pstViConfig)
    {
        SAMPLE_PRT("%s: null ptr\n", __FUNCTION__);
        return HI_FAILURE;
    }
    fd = open(MIPI_DEV_NODE, O_RDWR);
    if (fd < 0)
    {
        SAMPLE_PRT("open hi_mipi dev failed\n");
        return HI_FAILURE;
    }
    for (i = 0; i < pstViConfig->s32WorkingViNum; i++)
    {
        s32ViNum = pstViConfig->as32WorkingViId[i];
        pstViInfo = &pstViConfig->astViInfo[s32ViNum];
        devno = pstViInfo->stSnsInfo.MipiDev;
        s32Ret = ioctl(fd, HI_MIPI_RESET_MIPI, &devno);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("RESET_MIPI %d failed\n", devno);
            goto EXIT;
        }
    }
EXIT:
    close(fd);
    return s32Ret;
}

//============================================================================================
//反复位VI MIPI-CSI
//============================================================================================
HI_S32 SAMPLE_COMM_VI_UnresetMipi(SAMPLE_VI_CONFIG_S *pstViConfig)
{
    HI_S32 i = 0;
    HI_S32 s32ViNum = 0;
    HI_S32 s32Ret = HI_SUCCESS;
    HI_S32 fd;
    combo_dev_t devno = 0;
    SAMPLE_VI_INFO_S *pstViInfo = HI_NULL;
    if (!pstViConfig)
    {
        SAMPLE_PRT("%s: null ptr\n", __FUNCTION__);
        return HI_FAILURE;
    }
    fd = open(MIPI_DEV_NODE, O_RDWR);
    if (fd < 0)
    {
        SAMPLE_PRT("open hi_mipi dev failed\n");
        return HI_FAILURE;
    }
    for (i = 0; i < pstViConfig->s32WorkingViNum; i++)
    {
        s32ViNum = pstViConfig->as32WorkingViId[i];
        pstViInfo = &pstViConfig->astViInfo[s32ViNum];
        devno = pstViInfo->stSnsInfo.MipiDev;
        s32Ret = ioctl(fd, HI_MIPI_UNRESET_MIPI, &devno);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("UNRESET_MIPI %d failed\n", devno);
            goto EXIT;
        }
    }
EXIT:
    close(fd);
    return s32Ret;
}

//============================================================================================
//使能VI sensor时钟
//============================================================================================
HI_S32 SAMPLE_COMM_VI_EnableSensorClock(SAMPLE_VI_CONFIG_S *pstViConfig)
{
    HI_S32 s32Ret = HI_SUCCESS;
    HI_S32 fd;
    sns_clk_source_t SnsDev = 0;
    fd = open(MIPI_DEV_NODE, O_RDWR);
    if (fd < 0)
    {
        SAMPLE_PRT("open hi_mipi dev failed\n");
        return HI_FAILURE;
    }
    for (SnsDev = 0; SnsDev < SNS_MAX_CLK_SOURCE_NUM; SnsDev++)
    {
        s32Ret = ioctl(fd, HI_MIPI_ENABLE_SENSOR_CLOCK, &SnsDev);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MIPI_ENABLE_SENSOR_CLOCK failed\n");
            goto EXIT;
        }
    }
EXIT:
    close(fd);
    return s32Ret;
}

//============================================================================================
//关闭VI sensor时钟
//============================================================================================
HI_S32 SAMPLE_COMM_VI_DisableSensorClock(SAMPLE_VI_CONFIG_S *pstViConfig)
{
    HI_S32 s32Ret = HI_SUCCESS;
    HI_S32 fd;
    sns_clk_source_t SnsDev = 0;
    fd = open(MIPI_DEV_NODE, O_RDWR);
    if (fd < 0)
    {
        SAMPLE_PRT("open hi_mipi dev failed\n");
        return HI_FAILURE;
    }
    for (SnsDev = 0; SnsDev < SNS_MAX_CLK_SOURCE_NUM; SnsDev++)
    {
        s32Ret = ioctl(fd, HI_MIPI_DISABLE_SENSOR_CLOCK, &SnsDev);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MIPI_DISABLE_SENSOR_CLOCK failed\n");
            goto EXIT;
        }
    }
EXIT:
    close(fd);
    return s32Ret;
}

//============================================================================================
// VI sensor复位
//============================================================================================
HI_S32 SAMPLE_COMM_VI_ResetSensor(SAMPLE_VI_CONFIG_S *pstViConfig)
{
    HI_S32 s32Ret = HI_SUCCESS;
    HI_S32 fd;
    sns_rst_source_t SnsDev = 0;
    fd = open(MIPI_DEV_NODE, O_RDWR);
    if (fd < 0)
    {
        SAMPLE_PRT("open hi_mipi dev failed\n");
        return HI_FAILURE;
    }
    for (SnsDev = 0; SnsDev < SNS_MAX_RST_SOURCE_NUM; SnsDev++)
    {
        s32Ret = ioctl(fd, HI_MIPI_RESET_SENSOR, &SnsDev);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MIPI_RESET_SENSOR failed\n");
            goto EXIT;
        }
    }
EXIT:
    close(fd);
    return s32Ret;
}

//============================================================================================
// VI sensor反复位
//============================================================================================
HI_S32 SAMPLE_COMM_VI_UnresetSensor(SAMPLE_VI_CONFIG_S *pstViConfig)
{
    HI_S32 s32Ret = HI_SUCCESS;
    HI_S32 fd;
    sns_rst_source_t SnsDev = 0;
    fd = open(MIPI_DEV_NODE, O_RDWR);
    if (fd < 0)
    {
        SAMPLE_PRT("open hi_mipi dev failed\n");
        return HI_FAILURE;
    }
    for (SnsDev = 0; SnsDev < SNS_MAX_RST_SOURCE_NUM; SnsDev++)
    {
        s32Ret = ioctl(fd, HI_MIPI_UNRESET_SENSOR, &SnsDev);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MIPI_UNRESET_SENSOR failed\n");
            goto EXIT;
        }
    }
EXIT:
    close(fd);
    return s32Ret;
}

//============================================================================================
//设置VI mipi-csi属性
//============================================================================================
HI_S32 SAMPLE_COMM_VI_SetMipiAttr(SAMPLE_VI_CONFIG_S *pstViConfig)
{
    HI_S32 i = 0;
    HI_S32 s32ViNum = 0;
    HI_S32 s32Ret = HI_SUCCESS;
    HI_S32 fd;
    SAMPLE_VI_INFO_S *pstViInfo = HI_NULL;
    combo_dev_attr_t stcomboDevAttr;
    fd = open(MIPI_DEV_NODE, O_RDWR);
    if (fd < 0)
    {
        SAMPLE_PRT("open hi_mipi dev failed\n");
        return HI_FAILURE;
    }
    for (i = 0; i < pstViConfig->s32WorkingViNum; i++)
    {
        s32ViNum = pstViConfig->as32WorkingViId[i];
        pstViInfo = &pstViConfig->astViInfo[s32ViNum];
        switch (pstViInfo->stSnsInfo.enSnsType)
        {
        case OS01A:
            hi_memcpy(&stcomboDevAttr, sizeof(combo_dev_attr_t), &MIPI_4lane_CHN0_SENSOR_OS01A_12BIT_4M_NOWDR_ATTR, sizeof(combo_dev_attr_t));
            break;
        case OV426:
            hi_memcpy(&stcomboDevAttr, sizeof(combo_dev_attr_t), &MIPI_4lane_CHN0_SENSOR_OV426_10BIT_4M_NOWDR_ATTR, sizeof(combo_dev_attr_t));
            break;
        case OV9734:
            hi_memcpy(&stcomboDevAttr, sizeof(combo_dev_attr_t), &MIPI_4lane_CHN0_SENSOR_OV9734_10BIT_4M_NOWDR_ATTR, sizeof(combo_dev_attr_t));
            break;
        default:
            break;
        }
        stcomboDevAttr.devno = pstViInfo->stSnsInfo.MipiDev;
        // SAMPLE_PRT("============= MipiDev %d, SetMipiAttr enWDRMode: %d\n", pstViInfo->stSnsInfo.MipiDev, pstViInfo->stDevInfo.enWDRMode);
        s32Ret = ioctl(fd, HI_MIPI_SET_DEV_ATTR, &stcomboDevAttr);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("MIPI_SET_DEV_ATTR failed\n");
            goto EXIT;
        }
    }
EXIT:
    close(fd);
    return s32Ret;
}

//============================================================================================
//更新VI VPSS模式
//============================================================================================
HI_S32 SAMPLE_COMM_VI_UpdateVIVPSSMode(VI_VPSS_MODE_S *pstVIVPSSMode)
{
    HI_S32 i = 0;
    if (VI_OFFLINE_VPSS_OFFLINE == pstVIVPSSMode->aenMode[0])
    {
        for (i = 0; i < VI_MAX_PIPE_NUM; i++)
        {
            if (VI_OFFLINE_VPSS_ONLINE == pstVIVPSSMode->aenMode[i])
            {
                for (i = 0; i < VI_MAX_PIPE_NUM; i++)
                {
                    pstVIVPSSMode->aenMode[i] = VI_OFFLINE_VPSS_ONLINE;
                }
                break;
            }
        }
    }
    else if (VI_OFFLINE_VPSS_ONLINE == pstVIVPSSMode->aenMode[0])
    {
        for (i = 0; i < VI_MAX_PIPE_NUM; i++)
        {
            pstVIVPSSMode->aenMode[i] = pstVIVPSSMode->aenMode[0];
        }
    }
    return HI_SUCCESS;
}

//============================================================================================
//创建单个VI
//============================================================================================
static HI_S32 SAMPLE_COMM_VI_CreateSingleVi(SAMPLE_VI_INFO_S *pstViInfo)
{
    HI_S32 s32Ret = HI_SUCCESS;
    s32Ret = SAMPLE_COMM_VI_StartDev(pstViInfo);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("SAMPLE_COMM_VI_StartDev failed !\n");
        return HI_FAILURE;
    }
    // we should bind pipe,then creat pipe
    s32Ret = SAMPLE_COMM_VI_BindPipeDev(pstViInfo);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("SAMPLE_COMM_VI_BindPipeDev failed !\n");
        goto EXIT1;
    }
    s32Ret = SAMPLE_COMM_VI_StartViPipe(pstViInfo);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("SAMPLE_COMM_VI_StartViPipe failed !\n");
        goto EXIT1;
    }
    s32Ret = SAMPLE_COMM_VI_StartViChn(pstViInfo);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("SAMPLE_COMM_VI_StartViChn failed !\n");
        goto EXIT2;
    }
    return HI_SUCCESS;
EXIT2:
    SAMPLE_COMM_VI_StopViPipe(pstViInfo);
EXIT1:
    SAMPLE_COMM_VI_StopDev(pstViInfo);
    return s32Ret;
}

//============================================================================================
//启动VI   ISP   初始化摄像头, 注册sensor,AE,AWB库，初始化ISP-----------------use
//============================================================================================
HI_S32 SAMPLE_COMM_VI_StartIsp(SAMPLE_VI_INFO_S *pstViInfo)
    {
        HI_S32 i;
        HI_BOOL bNeedPipe;
        HI_S32 s32Ret = HI_SUCCESS;
        VI_PIPE ViPipe;
        HI_U32 u32SnsId;
        ISP_PUB_ATTR_S stPubAttr;
        VI_PIPE_ATTR_S stPipeAttr;

        switch (pstViInfo->stSnsInfo.enSnsType)
        {
        case OS01A:
            hi_memcpy(&stPipeAttr, sizeof(VI_PIPE_ATTR_S), &PIPE_ATTR_800x800_RAW12_420_3DNR_RFR, sizeof(VI_PIPE_ATTR_S));
            break;
        case OV426:
            hi_memcpy(&stPipeAttr, sizeof(VI_PIPE_ATTR_S), &PIPE_ATTR_400x400_RAW10_420_3DNR_RFR, sizeof(VI_PIPE_ATTR_S));
            break;
        case OV9734:
            hi_memcpy(&stPipeAttr, sizeof(VI_PIPE_ATTR_S), &PIPE_ATTR_720x720_RAW12_420_3DNR_RFR, sizeof(VI_PIPE_ATTR_S));
            break;
        default:
            break;
        }
        if (VI_PIPE_BYPASS_BE == stPipeAttr.enPipeBypassMode)
        {
            return HI_SUCCESS;
        }

        for (i = 0; i < WDR_MAX_PIPE_NUM; i++)
        {
            if (pstViInfo->stPipeInfo.aPipe[i] >= 0 && pstViInfo->stPipeInfo.aPipe[i] < VI_MAX_PIPE_NUM)
            {
                ViPipe = pstViInfo->stPipeInfo.aPipe[i];
                u32SnsId = pstViInfo->stSnsInfo.s32SnsId;
                switch (pstViInfo->stSnsInfo.enSnsType)
                {

                case OS01A:
                    memcpy(&stPubAttr, &ISP_PUB_ATTR_OS01A_MIPI_4M_30FPS, sizeof(ISP_PUB_ATTR_S));
                    break;

                case OV426:
                    memcpy(&stPubAttr, &ISP_PUB_ATTR_OV426_MIPI_4M_30FPS, sizeof(ISP_PUB_ATTR_S));
                    break;
                case OV9734:
                    memcpy(&stPubAttr, &ISP_PUB_ATTR_OV9734_MIPI_4M_30FPS, sizeof(ISP_PUB_ATTR_S));
                    break;
                default:
                    break;
                }

                stPubAttr.enWDRMode = pstViInfo->stDevInfo.enWDRMode;

                if (WDR_MODE_NONE == pstViInfo->stDevInfo.enWDRMode)
                {
                    bNeedPipe = HI_TRUE;
                }
                else
                {
                    bNeedPipe = (i > 0) ? HI_FALSE : HI_TRUE;
                }

                if (HI_TRUE != bNeedPipe)
                {
                    continue;
                }

                //注册sensor库---------------------------------------------------------------------------
                s32Ret = SAMPLE_COMM_ISP_Sensor_Regiter_callback(ViPipe, u32SnsId);
                if (HI_SUCCESS != s32Ret)
                {
                    SAMPLE_PRT("register sensor %d to ISP %d failed\n", u32SnsId, ViPipe);
                    SAMPLE_COMM_ISP_Stop(ViPipe);
                    return HI_FAILURE;
                }

                if (((pstViInfo->stSnapInfo.bDoublePipe) && (pstViInfo->stSnapInfo.SnapPipe == ViPipe)) || (pstViInfo->stPipeInfo.bMultiPipe && i > 0))
                {
                    s32Ret = SAMPLE_COMM_ISP_BindSns(ViPipe, u32SnsId, pstViInfo->stSnsInfo.enSnsType, -1);

                    if (HI_SUCCESS != s32Ret)
                    {
                        SAMPLE_PRT("register sensor %d bus id %d failed\n", u32SnsId, pstViInfo->stSnsInfo.s32BusId);
                        SAMPLE_COMM_ISP_Stop(ViPipe);
                        return HI_FAILURE;
                    }
                }
                else
                {
                    s32Ret = SAMPLE_COMM_ISP_BindSns(ViPipe, u32SnsId, pstViInfo->stSnsInfo.enSnsType, pstViInfo->stSnsInfo.s32BusId);

                    if (HI_SUCCESS != s32Ret)
                    {
                        SAMPLE_PRT("register sensor %d bus id %d failed\n", u32SnsId, pstViInfo->stSnsInfo.s32BusId);
                        SAMPLE_COMM_ISP_Stop(ViPipe);
                        return HI_FAILURE;
                    }
                }

                //注册海思AE算法库-----------------------------------------------------------
                s32Ret = SAMPLE_COMM_ISP_Aelib_Callback(ViPipe);
                if (HI_SUCCESS != s32Ret)
                {
                    SAMPLE_PRT("SAMPLE_COMM_ISP_Aelib_Callback failed\n");
                    SAMPLE_COMM_ISP_Stop(ViPipe);
                    return HI_FAILURE;
                }

                //注册海思AWB算法库-----------------------------------------------------------
                s32Ret = SAMPLE_COMM_ISP_Awblib_Callback(ViPipe);
                if (HI_SUCCESS != s32Ret)
                {
                    SAMPLE_PRT("SAMPLE_COMM_ISP_Awblib_Callback failed\n");
                    SAMPLE_COMM_ISP_Stop(ViPipe);
                    return HI_FAILURE;
                }

                //初始化ISP外部寄存器----------------------------------------------------------
                s32Ret = HI_MPI_ISP_MemInit(ViPipe);
                if (s32Ret != HI_SUCCESS)
                {
                    SAMPLE_PRT("Init Ext memory failed with %#x!\n", s32Ret);
                    SAMPLE_COMM_ISP_Stop(ViPipe);
                    return HI_FAILURE;
                }

                //配置图像公共属性--------------------------------------------------------------
                s32Ret = HI_MPI_ISP_SetPubAttr(ViPipe, &stPubAttr);
                if (s32Ret != HI_SUCCESS)
                {
                    SAMPLE_PRT("SetPubAttr failed with %#x!\n", s32Ret);
                    SAMPLE_COMM_ISP_Stop(ViPipe);
                    return HI_FAILURE;
                }

                //初始化ISP Firmware-----------------------------------------------------------
                s32Ret = HI_MPI_ISP_Init(ViPipe);
                if (s32Ret != HI_SUCCESS)
                {
                    SAMPLE_PRT("ISP Init failed with %#x!\n", s32Ret);
                    SAMPLE_COMM_ISP_Stop(ViPipe);
                    return HI_FAILURE;
                }

                // HI_MPI_ISP_Run单独启动线程运行-------------------------------------------------
                s32Ret = SAMPLE_COMM_ISP_Run(ViPipe);
                if (s32Ret != HI_SUCCESS)
                {
                    SAMPLE_PRT("ISP Run failed with %#x!\n", s32Ret);
                    SAMPLE_COMM_ISP_Stop(ViPipe);
                    return HI_FAILURE;
                }

                /*
                启动VI/VO等业务.................................................................
                ..............................................................................
                停止VI/VO等业务.................................................................
                s32Ret = HI_MPI_ISP_Exit(ViPipe);
                if (HI_SUCCESS != s32Ret)
                {
                    printf(”isp exit failed!\n”);
                    return s32Ret;
                }
                pthread_join(isp_pid, 0);
                return HI_SUCCESS;
                */
            }
        }

        return s32Ret;
    }

//============================================================================================
//停止VI ISP
//============================================================================================
HI_S32 SAMPLE_COMM_VI_StopIsp(SAMPLE_VI_INFO_S *pstViInfo)
{
    HI_S32 i;
    HI_BOOL bNeedPipe;
    VI_PIPE ViPipe;
    for (i = 0; i < WDR_MAX_PIPE_NUM; i++)
    {
        if (pstViInfo->stPipeInfo.aPipe[i] >= 0 && pstViInfo->stPipeInfo.aPipe[i] < VI_MAX_PIPE_NUM)
        {
            ViPipe = pstViInfo->stPipeInfo.aPipe[i];
            if (WDR_MODE_NONE == pstViInfo->stDevInfo.enWDRMode)
            {
                bNeedPipe = HI_TRUE;
            }
            else
            {
                bNeedPipe = (i > 0) ? HI_FALSE : HI_TRUE;
            }
            if (HI_TRUE != bNeedPipe)
            {
                continue;
            }
            SAMPLE_COMM_ISP_Stop(ViPipe);
        }
    }
    return HI_SUCCESS;
}

//============================================================================================
//启动VI MIPI                  本文夹下的main.c文件内调用--------------------- [main.c step 2.3.1]
//============================================================================================
HI_S32 SAMPLE_COMM_VI_StartMIPI(SAMPLE_VI_CONFIG_S *pstViConfig)
    {
        HI_S32 s32Ret = HI_SUCCESS;
        lane_divide_mode_t lane_divide_mode = LANE_DIVIDE_MODE_0;
        s32Ret = SAMPLE_COMM_VI_SetMipiHsMode(lane_divide_mode);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_SetMipiHsMode failed!\n");
            return HI_FAILURE;
        }
        s32Ret = SAMPLE_COMM_VI_EnableMipiClock(pstViConfig);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_EnableMipiClock failed!\n");

            return HI_FAILURE;
        }

        s32Ret = SAMPLE_COMM_VI_ResetMipi(pstViConfig);

        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_ResetMipi failed!\n");

            return HI_FAILURE;
        }

        s32Ret = SAMPLE_COMM_VI_EnableSensorClock(pstViConfig);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_EnableSensorClock failed!\n");

            return HI_FAILURE;
        }

        s32Ret = SAMPLE_COMM_VI_ResetSensor(pstViConfig);

        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_ResetSensor failed!\n");

            return HI_FAILURE;
        }

        s32Ret = SAMPLE_COMM_VI_SetMipiAttr(pstViConfig);

        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_SetMipiAttr failed!\n");

            return HI_FAILURE;
        }

        s32Ret = SAMPLE_COMM_VI_UnresetMipi(pstViConfig);

        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_UnresetMipi failed!\n");

            return HI_FAILURE;
        }

        s32Ret = SAMPLE_COMM_VI_UnresetSensor(pstViConfig);

        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_UnresetSensor failed!\n");

            return HI_FAILURE;
        }

        return HI_SUCCESS;
    }

//============================================================================================
//停止VI mipi
//============================================================================================
HI_S32 SAMPLE_COMM_VI_StopMIPI(SAMPLE_VI_CONFIG_S *pstViConfig)
    {
        HI_S32 s32Ret = HI_SUCCESS;
        s32Ret = SAMPLE_COMM_VI_ResetSensor(pstViConfig);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_ResetSensor failed!\n");

            return HI_FAILURE;
        }

        s32Ret = SAMPLE_COMM_VI_DisableSensorClock(pstViConfig);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_DisableSensorClock failed!\n");

            return HI_FAILURE;
        }

        s32Ret = SAMPLE_COMM_VI_ResetMipi(pstViConfig);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_ResetMipi failed!\n");

            return HI_FAILURE;
        }

        s32Ret = SAMPLE_COMM_VI_DisableMipiClock(pstViConfig);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_DisableMipiClock failed!\n");

            return HI_FAILURE;
        }

        return HI_SUCCESS;
    }

//============================================================================================
//设置VI参数 -                  本文夹下的main.c文件内调用--------------------- [main.c step 2.3.2]
//============================================================================================
HI_S32 SAMPLE_COMM_VI_SetParam(SAMPLE_VI_CONFIG_S *pstViConfig)
    {
        HI_S32 i;
        HI_S32 s32ViNum;
        HI_S32 s32Ret;
        VI_PIPE ViPipe;
        VI_VPSS_MODE_S stVIVPSSMode;
        SAMPLE_VI_INFO_S *pstViInfo = HI_NULL;
        s32Ret = HI_MPI_SYS_GetVIVPSSMode(&stVIVPSSMode);

        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("Get VI-VPSS mode Param failed with %#x!\n", s32Ret);

            return HI_FAILURE;
        }

        for (i = 0; i < pstViConfig->s32WorkingViNum; i++)
        {
            s32ViNum = pstViConfig->as32WorkingViId[i];
            pstViInfo = &pstViConfig->astViInfo[s32ViNum];
            ViPipe = pstViInfo->stPipeInfo.aPipe[0];
            stVIVPSSMode.aenMode[ViPipe] = pstViInfo->stPipeInfo.enMastPipeMode;

            if ((pstViInfo->stPipeInfo.bMultiPipe == HI_TRUE) || (VI_OFFLINE_VPSS_ONLINE == pstViInfo->stPipeInfo.enMastPipeMode))
            {
                SAMPLE_COMM_VI_UpdateVIVPSSMode(&stVIVPSSMode);

                ViPipe = pstViInfo->stPipeInfo.aPipe[1];
                if (ViPipe != -1)
                {
                    stVIVPSSMode.aenMode[ViPipe] = pstViInfo->stPipeInfo.enMastPipeMode;
                }

                ViPipe = pstViInfo->stPipeInfo.aPipe[2];
                if (ViPipe != -1)
                {
                    stVIVPSSMode.aenMode[ViPipe] = pstViInfo->stPipeInfo.enMastPipeMode;
                }

                ViPipe = pstViInfo->stPipeInfo.aPipe[3];
                if (ViPipe != -1)
                {
                    stVIVPSSMode.aenMode[ViPipe] = pstViInfo->stPipeInfo.enMastPipeMode;
                }
            }

            if ((pstViInfo->stSnapInfo.bSnap) && (pstViInfo->stSnapInfo.bDoublePipe))
            {
                ViPipe = pstViInfo->stPipeInfo.aPipe[1];
                if (ViPipe != -1)
                {
                    stVIVPSSMode.aenMode[ViPipe] = pstViInfo->stSnapInfo.enSnapPipeMode;
                }
            }
        }
        s32Ret = HI_MPI_SYS_SetVIVPSSMode(&stVIVPSSMode);

        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("Set VI-VPSS mode Param failed with %#x!\n", s32Ret);

            return HI_FAILURE;
        }

        return HI_SUCCESS;
    }

//============================================================================================
//销毁一个 VI PIPE。
//============================================================================================
static HI_S32 SAMPLE_COMM_VI_DestroySingleVi(SAMPLE_VI_INFO_S *pstViInfo)
    {
        SAMPLE_COMM_VI_StopViChn(pstViInfo);
        SAMPLE_COMM_VI_StopViPipe(pstViInfo);
        SAMPLE_COMM_VI_StopDev(pstViInfo);
        return HI_SUCCESS;
    }

//============================================================================================
//创建一个 VI PIPE             本文夹下的main.c文件内调用--------------------- [main.c step 2.3.3]
//============================================================================================
HI_S32 SAMPLE_COMM_VI_CreateVi(SAMPLE_VI_CONFIG_S *pstViConfig)
    {
        HI_S32 i, j;
        HI_S32 s32ViNum;
        HI_S32 s32Ret = HI_SUCCESS;
        SAMPLE_VI_INFO_S *pstViInfo = HI_NULL;

        for (i = 0; i < pstViConfig->s32WorkingViNum; i++)
        {
            s32ViNum = pstViConfig->as32WorkingViId[i];
            pstViInfo = &pstViConfig->astViInfo[s32ViNum];

            s32Ret = SAMPLE_COMM_VI_CreateSingleVi(pstViInfo);

            if (s32Ret != HI_SUCCESS)
            {
                SAMPLE_PRT("SAMPLE_COMM_VI_CreateSingleVi failed !\n");
                goto EXIT;
            }
        }

        return HI_SUCCESS;
    EXIT:

        for (j = 0; j < i; j++)
        {
            s32ViNum = pstViConfig->as32WorkingViId[j];
            pstViInfo = &pstViConfig->astViInfo[s32ViNum];

            SAMPLE_COMM_VI_DestroySingleVi(pstViInfo);
        }

        return s32Ret;
    }

//============================================================================================
//销毁all  VI PIPE。           本文夹下的main.c文件内调用--------------------- [main.c step 2.3.5]
//============================================================================================
HI_S32 SAMPLE_COMM_VI_DestroyVi(SAMPLE_VI_CONFIG_S *pstViConfig)
    {
        HI_S32 i;
        HI_S32 s32ViNum;
        SAMPLE_VI_INFO_S *pstViInfo = HI_NULL;
        for (i = 0; i < pstViConfig->s32WorkingViNum; i++)
        {
            s32ViNum = pstViConfig->as32WorkingViId[i];
            pstViInfo = &pstViConfig->astViInfo[s32ViNum];
            SAMPLE_COMM_VI_StopViChn(pstViInfo);
            SAMPLE_COMM_VI_StopViPipe(pstViInfo);
            SAMPLE_COMM_VI_StopDev(pstViInfo);
        }

        return HI_SUCCESS;
    }

//============================================================================================
//创建VI ISP                   本文夹下的main.c文件内调用--------------------- [main.c step 2.3.4]
//============================================================================================
HI_S32 SAMPLE_COMM_VI_CreateIsp(SAMPLE_VI_CONFIG_S *pstViConfig)
    {
        HI_S32 i;
        HI_S32 s32ViNum;
        HI_S32 s32Ret = HI_SUCCESS;

        SAMPLE_VI_INFO_S *pstViInfo = HI_NULL;

        for (i = 0; i < pstViConfig->s32WorkingViNum; i++)
        {
            s32ViNum = pstViConfig->as32WorkingViId[i];
            pstViInfo = &pstViConfig->astViInfo[s32ViNum];
            s32Ret = SAMPLE_COMM_VI_StartIsp(pstViInfo);

            if (s32Ret != HI_SUCCESS)
            {
                SAMPLE_PRT("SAMPLE_COMM_VI_StartIsp failed !\n");
                return HI_FAILURE;
            }
        }

        return HI_SUCCESS;
    }

//============================================================================================
//销毁VI ISP
//============================================================================================
HI_S32 SAMPLE_COMM_VI_DestroyIsp(SAMPLE_VI_CONFIG_S *pstViConfig)
    {
        HI_S32 i;
        HI_S32 s32ViNum;
        HI_S32 s32Ret = HI_SUCCESS;
        SAMPLE_VI_INFO_S *pstViInfo = HI_NULL;

        for (i = 0; i < pstViConfig->s32WorkingViNum; i++)
        {
            s32ViNum = pstViConfig->as32WorkingViId[i];
            pstViInfo = &pstViConfig->astViInfo[s32ViNum];
            s32Ret = SAMPLE_COMM_VI_StopIsp(pstViInfo);

            if (s32Ret != HI_SUCCESS)
            {
                SAMPLE_PRT("SAMPLE_COMM_VI_StopIsp failed !\n");
                return HI_FAILURE;
            }
        }

        return HI_SUCCESS;
    }

//============================================================================================
//获取VI BUFFER信息
//============================================================================================
HI_S32 SAMPLE_VI_GetFrameBlkInfo(SAMPLE_VI_FRAME_CONFIG_S *pstFrmCfg, HI_S32 s32FrmCnt, SAMPLE_VI_FRAME_INFO_S *pastViFrameInfo)
    {
        HI_U32 i = 0;
        HI_U32 u32Stride;
        HI_U32 u32LStride;
        HI_U32 u32CStride;
        HI_U32 u32LumaSize = 0;
        HI_U32 u32ChrmSize = 0;
        HI_U32 u32Size;
        HI_U64 u64PhyAddr;
        HI_U8 *pVirAddr;
        VB_POOL u32PoolId;
        VB_BLK VbBlk;
        VB_POOL_CONFIG_S stVbPoolCfg;

        u32Stride = ALIGN_UP((pstFrmCfg->u32Width * 8 + 7) >> 3, DEFAULT_ALIGN);
        u32LStride = u32Stride;
        u32CStride = u32Stride;
        u32Size = u32Stride * pstFrmCfg->u32Height * 3 / 2;
        u32LumaSize = u32Stride * pstFrmCfg->u32Height;
        u32ChrmSize = u32Stride * pstFrmCfg->u32Height / 4;
        memset(&stVbPoolCfg, 0, sizeof(VB_POOL_CONFIG_S));
        stVbPoolCfg.u64BlkSize = u32Size;
        stVbPoolCfg.u32BlkCnt = s32FrmCnt;
        stVbPoolCfg.enRemapMode = VB_REMAP_MODE_NONE;
        u32PoolId = HI_MPI_VB_CreatePool(&stVbPoolCfg);
        if (VB_INVALID_POOLID == u32PoolId)
        {
            SAMPLE_PRT("HI_MPI_VB_CreatePool failed!\n");
            return HI_FAILURE;
        }

        for (i = 0; i < s32FrmCnt; i++)
        {
            VbBlk = HI_MPI_VB_GetBlock(u32PoolId, u32Size, HI_NULL);
            if (VB_INVALID_HANDLE == VbBlk)
            {
                SAMPLE_PRT("HI_MPI_VB_GetBlock err! size:%d\n", u32Size);
                return HI_FAILURE;
            }

            u64PhyAddr = HI_MPI_VB_Handle2PhysAddr(VbBlk);
            if (0 == u64PhyAddr)
            {
                SAMPLE_PRT("HI_MPI_VB_Handle2PhysAddr err!\n");
                return HI_FAILURE;
            }

            pVirAddr = (HI_U8 *)HI_MPI_SYS_Mmap(u64PhyAddr, u32Size);
            if (NULL == pVirAddr)
            {
                SAMPLE_PRT("HI_MPI_SYS_Mmap err!\n");
                return HI_FAILURE;
            }

            pastViFrameInfo[i].stVideoFrameInfo.u32PoolId = u32PoolId;
            pastViFrameInfo[i].stVideoFrameInfo.enModId = HI_ID_VI;
            pastViFrameInfo[i].stVideoFrameInfo.stVFrame.u64PhyAddr[0] = u64PhyAddr;
            pastViFrameInfo[i].stVideoFrameInfo.stVFrame.u64PhyAddr[1] = pastViFrameInfo[i].stVideoFrameInfo.stVFrame.u64PhyAddr[0] + u32LumaSize;
            pastViFrameInfo[i].stVideoFrameInfo.stVFrame.u64PhyAddr[2] = pastViFrameInfo[i].stVideoFrameInfo.stVFrame.u64PhyAddr[1] + u32ChrmSize;

            pastViFrameInfo[i].stVideoFrameInfo.stVFrame.u64VirAddr[0] = (HI_U64)(HI_UL)pVirAddr;
            pastViFrameInfo[i].stVideoFrameInfo.stVFrame.u64VirAddr[1] = pastViFrameInfo[i].stVideoFrameInfo.stVFrame.u64VirAddr[0] + u32LumaSize;
            pastViFrameInfo[i].stVideoFrameInfo.stVFrame.u64VirAddr[2] = pastViFrameInfo[i].stVideoFrameInfo.stVFrame.u64VirAddr[1] + u32ChrmSize;

            pastViFrameInfo[i].stVideoFrameInfo.stVFrame.u32Stride[0] = u32LStride;
            pastViFrameInfo[i].stVideoFrameInfo.stVFrame.u32Stride[1] = u32CStride;
            pastViFrameInfo[i].stVideoFrameInfo.stVFrame.u32Stride[2] = u32CStride;

            pastViFrameInfo[i].stVideoFrameInfo.stVFrame.u32Width = pstFrmCfg->u32Width;
            pastViFrameInfo[i].stVideoFrameInfo.stVFrame.u32Height = pstFrmCfg->u32Height;
            pastViFrameInfo[i].stVideoFrameInfo.stVFrame.enPixelFormat = pstFrmCfg->enPixelFormat;
            pastViFrameInfo[i].stVideoFrameInfo.stVFrame.enVideoFormat = pstFrmCfg->enVideoFormat;
            pastViFrameInfo[i].stVideoFrameInfo.stVFrame.enCompressMode = pstFrmCfg->enCompressMode;
            pastViFrameInfo[i].stVideoFrameInfo.stVFrame.enDynamicRange = pstFrmCfg->enDynamicRange;
            pastViFrameInfo[i].stVideoFrameInfo.stVFrame.enField = VIDEO_FIELD_FRAME;
            pastViFrameInfo[i].stVideoFrameInfo.stVFrame.enColorGamut = COLOR_GAMUT_BT709;

            pastViFrameInfo[i].VbBlk = VbBlk;
            pastViFrameInfo[i].u32Size = u32Size;
        }

        return HI_SUCCESS;
    }

//============================================================================================
//读取一帧 VI frame
//============================================================================================
HI_VOID SAMPLE_VI_ReadOneFrame(FILE *fp, HI_U8 *pY, HI_U8 *pU, HI_U8 *pV, HI_U32 width, HI_U32 height, HI_U32 stride, HI_U32 stride2)
    {
        HI_U8 *pDst;
        HI_U32 u32Row;
        pDst = pY;

        for (u32Row = 0; u32Row < height; u32Row++)
        {
            fread(pDst, width, 1, fp);
            pDst += stride;
        }
        pDst = pU;
        for (u32Row = 0; u32Row < height / 2; u32Row++)
        {
            fread(pDst, width / 2, 1, fp);
            pDst += stride2;
        }

        pDst = pV;
        for (u32Row = 0; u32Row < height / 2; u32Row++)
        {
            fread(pDst, width / 2, 1, fp);
            pDst += stride2;
        }

        char temp[1];
        fread(temp, 1, 1, fp);

        if (feof(fp) != 0)
        {
            printf("file is EOF!\n");
        }
        else
        {
            fseek(fp, ftell(fp) - 1, SEEK_SET);
        }
    }

//============================================================================================
// VI_PlanToSemi
//============================================================================================
HI_S32 SAMPLE_VI_PlanToSemi(HI_U8 *pY, HI_S32 yStride, HI_U8 *pU, HI_S32 uStride, HI_U8 *pV, HI_S32 vStride, HI_S32 picWidth, HI_S32 picHeight)
    {
        HI_S32 i;
        HI_U8 *pTmpU, *ptu;
        HI_U8 *pTmpV, *ptv;
        VO_CSC_S stVideoCSC = {0}; // add 2022-03-27  Ref-->35inchold

        HI_S32 s32HafW = uStride >> 1;
        HI_S32 s32HafH = picHeight >> 1;
        HI_S32 s32Size = s32HafW * s32HafH;

        pTmpU = malloc(s32Size);
        ptu = pTmpU;
        pTmpV = malloc(s32Size);
        ptv = pTmpV;

        CHECK_RET(HI_MPI_VO_GetGraphicLayerCSC(GRAPHICS_LAYER_G0, &stVideoCSC), "HI_MPI_VO_GetGraphicLayerCSC(0)"); // add 2022-03-27  Ref-->35inchold
        stVideoCSC.enCscMatrix = VO_CSC_MATRIX_RGB_TO_BT601_TV;                                                     // add 2022-03-27  Ref-->35inchold
        CHECK_RET(HI_MPI_VO_SetGraphicLayerCSC(GRAPHICS_LAYER_G0, &stVideoCSC), "HI_MPI_VO_SetGraphicLayerCSC(0)"); // add 2022-03-27  Ref-->35inchold

        memcpy(pTmpU, pU, s32Size);
        memcpy(pTmpV, pV, s32Size);

        for (i = 0; i < s32Size >> 1; i++)
        {
            *pU++ = *pTmpV++;
            *pU++ = *pTmpU++;
        }
        for (i = 0; i < s32Size >> 1; i++)
        {
            *pV++ = *pTmpV++;
            *pV++ = *pTmpU++;
        }

        free(ptu);
        free(ptv);

        return HI_SUCCESS;
    }

//============================================================================================
// ReadYuvFile
//============================================================================================
static HI_VOID SAMPLE_VI_COMM_ReadYuvFile(FILE *pfd, VIDEO_FRAME_INFO_S *pstVideoFrameInfo)
    {
        SAMPLE_VI_ReadOneFrame(pfd, (HI_U8 *)(HI_UL)pstVideoFrameInfo->stVFrame.u64VirAddr[0],
                               (HI_U8 *)(HI_UL)pstVideoFrameInfo->stVFrame.u64VirAddr[1], (HI_U8 *)(HI_UL)pstVideoFrameInfo->stVFrame.u64VirAddr[2],
                               pstVideoFrameInfo->stVFrame.u32Width, pstVideoFrameInfo->stVFrame.u32Height,
                               pstVideoFrameInfo->stVFrame.u32Stride[0], pstVideoFrameInfo->stVFrame.u32Stride[1] >> 1);

        sleep(1);
        SAMPLE_VI_PlanToSemi((HI_U8 *)(HI_UL)pstVideoFrameInfo->stVFrame.u64VirAddr[0], pstVideoFrameInfo->stVFrame.u32Stride[0],
                             (HI_U8 *)(HI_UL)pstVideoFrameInfo->stVFrame.u64VirAddr[1], pstVideoFrameInfo->stVFrame.u32Stride[1],
                             (HI_U8 *)(HI_UL)pstVideoFrameInfo->stVFrame.u64VirAddr[2], pstVideoFrameInfo->stVFrame.u32Stride[1],
                             pstVideoFrameInfo->stVFrame.u32Width, pstVideoFrameInfo->stVFrame.u32Height);
    }

//============================================================================================
// VI_Load_UserPic
//============================================================================================
HI_S32 SAMPLE_COMM_VI_Load_UserPic(const char *pszYuvFile, VI_USERPIC_ATTR_S *pstUsrPic, SAMPLE_VI_FRAME_INFO_S *pstViFrameInfo)
    {
        FILE *pfd;
        SAMPLE_VI_FRAME_CONFIG_S stFrmCfg;
        HI_S32 s32Ret;

        stFrmCfg.u32Width = pstUsrPic->unUsrPic.stUsrPicFrm.stVFrame.u32Width;
        stFrmCfg.u32Height = pstUsrPic->unUsrPic.stUsrPicFrm.stVFrame.u32Height;
        stFrmCfg.u32ByteAlign = 0;
        stFrmCfg.enPixelFormat = pstUsrPic->unUsrPic.stUsrPicFrm.stVFrame.enPixelFormat;
        stFrmCfg.enCompressMode = COMPRESS_MODE_NONE;
        stFrmCfg.enVideoFormat = VIDEO_FORMAT_LINEAR;
        stFrmCfg.enDynamicRange = DYNAMIC_RANGE_SDR8;

        s32Ret = SAMPLE_VI_GetFrameBlkInfo(&stFrmCfg, 1, pstViFrameInfo);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_VI_GetFrameBlkInfo failed!\n");
            return s32Ret;
        }

        memcpy(&pstUsrPic->unUsrPic.stUsrPicFrm, &pstViFrameInfo->stVideoFrameInfo, sizeof(VIDEO_FRAME_INFO_S));

        printf("====to open YUV file: %s. \n", pszYuvFile);
        pfd = fopen(pszYuvFile, "rb");
        if (!pfd)
        {
            SAMPLE_PRT("open file -> %s fail \n", pszYuvFile);
        }

        SAMPLE_VI_COMM_ReadYuvFile(pfd, &pstUsrPic->unUsrPic.stUsrPicFrm);

        fclose(pfd);

        return HI_SUCCESS;
    }

//============================================================================================
// VI_StartVi   ----------------本文夹下的main.c文件内调用--------------------- [main.c step 2.3.0]
//============================================================================================
HI_S32 SAMPLE_COMM_VI_StartVi(SAMPLE_VI_CONFIG_S *pstViConfig)
    {
        HI_S32 s32Ret = HI_SUCCESS;
        s32Ret = SAMPLE_COMM_VI_StartMIPI(pstViConfig);
        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_StartMIPI failed!\n");
            return HI_FAILURE;
        }

        s32Ret = SAMPLE_COMM_VI_SetParam(pstViConfig);
        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_SetParam failed!\n");
            return HI_FAILURE;
        }

        s32Ret = SAMPLE_COMM_VI_CreateVi(pstViConfig);
        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("SAMPLE_COMM_VI_CreateVi failed!\n");
            return HI_FAILURE;
        }

        s32Ret = SAMPLE_COMM_VI_CreateIsp(pstViConfig);
        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_COMM_VI_DestroyVi(pstViConfig);
            SAMPLE_PRT("SAMPLE_COMM_VI_CreateIsp failed!\n");
            return HI_FAILURE;
        }

#if 0
    //=======================================================================================================
    // 创建  hdmi  freambuffer
    VI_USERPIC_ATTR_S userPic;
    SAMPLE_VI_FRAME_INFO_S stViFrameInfo;
    userPic.enUsrPicMode = VI_USERPIC_MODE_PIC;
    userPic.unUsrPic.stUsrPicFrm.stVFrame.u32Width = 1920;
    userPic.unUsrPic.stUsrPicFrm.stVFrame.u32Height = 1080;
    userPic.unUsrPic.stUsrPicFrm.stVFrame.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    SAMPLE_COMM_VI_Load_UserPic("./res/UsePic_1920_1080_420.yuv", &userPic, &stViFrameInfo);
    HI_MPI_VI_SetUserPic(0, &userPic);
    HI_MPI_VI_EnableUserPic(0);
#endif

        return s32Ret;
    }

//============================================================================================
// VI_StopVi
//============================================================================================
HI_S32 SAMPLE_COMM_VI_StopVi(SAMPLE_VI_CONFIG_S *pstViConfig)
    {
        SAMPLE_COMM_VI_DestroyIsp(pstViConfig);
        SAMPLE_COMM_VI_DestroyVi(pstViConfig);
        SAMPLE_COMM_VI_StopMIPI(pstViConfig);
        return HI_SUCCESS;
    }

//=======================================================================================================
// 创建  hdmi  freambuffer
//=======================================================================================================
HI_S32 mppVoHdmiCreateFb(void)
    {
        struct fb_var_screeninfo var;
        static struct fb_bitfield s_a32 = {24, 8, 0};
        static struct fb_bitfield s_r32 = {16, 8, 0};
        static struct fb_bitfield s_g32 = {8, 8, 0};
        static struct fb_bitfield s_b32 = {0, 8, 0};
        HIFB_POINT_S stPoint = {0, 0};
        VO_CSC_S stVideoCSC = {0};
        HI_BOOL bShow = HI_TRUE;
        HI_S32 fd;
        fd = open("/dev/fb0", O_RDWR, 0);
        if (fd < 0)
        {
            printf("open fb0 failed!\n");
            return HI_FAILURE;
        }
        CHECK_RET(HI_MPI_VO_GetGraphicLayerCSC(GRAPHICS_LAYER_G0, &stVideoCSC), "HI_MPI_VO_GetGraphicLayerCSC(0)");
        stVideoCSC.enCscMatrix = VO_CSC_MATRIX_RGB_TO_BT601_TV;
        CHECK_RET(HI_MPI_VO_SetGraphicLayerCSC(GRAPHICS_LAYER_G0, &stVideoCSC), "HI_MPI_VO_SetGraphicLayerCSC(0)");
        if (ioctl(fd, FBIOPUT_SHOW_HIFB, &bShow) < 0)
        {
            printf("FBIOPUT_SHOW_HIFB failed!\n");
            goto Error;
        }
        if (ioctl(fd, FBIOPUT_SCREEN_ORIGIN_HIFB, &stPoint) < 0)
        {
            printf("set screen original show position failed!\n");
            goto Error;
        }
        if (ioctl(fd, FBIOGET_VSCREENINFO, &var) < 0)
        {
            printf("Get variable screen info failed!\n");
            goto Error;
        }
        var.transp = s_a32;
        var.red = s_r32;
        var.green = s_g32;
        var.blue = s_b32;
        var.bits_per_pixel = 32;
        switch(hdmi_disp_mode)
        {
            case HDMI_1080P:
                var.xres_virtual = 1920;
                var.yres_virtual = 1080*2;
                var.xres = 1920;
                var.yres = 1080;
            break;
            case HDMI_1920x1200:
                var.xres_virtual = 1920;
                var.yres_virtual = 1200*2;
                var.xres = 1920;
                var.yres = 1200;
            break;
        }
        var.activate = FB_ACTIVATE_NOW;
        if (ioctl(fd, FBIOPUT_VSCREENINFO, &var) < 0)
        {
            printf("Put variable screen info failed!\n");
            goto Error;
        }
        if (ioctl(fd, FBIOPUT_SHOW_HIFB, &bShow) < 0)
        {
            printf("FBIOPUT_SHOW_HIFB failed!\n");
            goto Error;
        }
        fbp = (unsigned char *)mmap(0, 1920 * 1080 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        return HI_SUCCESS;
    Error:
        close(fd);
        return HI_FAILURE;
    }

//=======================================================================================================
// 创建  mipi  freambuffer
//=======================================================================================================
HI_S32 mppVoMipiCreateFb(void)
    {
        HIFB_LAYER_INFO_S stLayerInfo = {0};
        HI_BOOL bShow = HI_TRUE;
        HIFB_POINT_S stPoint = {0};
        struct fb_var_screeninfo stVarInfo;
        VO_CSC_S stVideoCSC = {0};
        HI_S32 fd;
        static struct fb_bitfield s_a32 = {24, 8, 0};
        static struct fb_bitfield s_r32 = {16, 8, 0};
        static struct fb_bitfield s_g32 = {8, 8, 0};
        static struct fb_bitfield s_b32 = {0, 8, 0};
        fd = open("/dev/fb0", O_RDWR, 0);
        if (fd < 0)
        {
            printf("open fb0 failed!\n");
            return HI_FAILURE;
        }
        CHECK_RET(HI_MPI_VO_GetGraphicLayerCSC(GRAPHICS_LAYER_G0, &stVideoCSC), "HI_MPI_VO_GetGraphicLayerCSC(0)");
        stVideoCSC.enCscMatrix = VO_CSC_MATRIX_IDENTITY;
        CHECK_RET(HI_MPI_VO_SetGraphicLayerCSC(GRAPHICS_LAYER_G0, &stVideoCSC), "HI_MPI_VO_SetGraphicLayerCSC(0)");
        if (ioctl(fd, FBIOPUT_SCREEN_ORIGIN_HIFB, &stPoint) < 0)
        {
            printf("set screen original show position failed!\n");
            goto Error;
        }
        if (ioctl(fd, FBIOGET_VSCREENINFO, &stVarInfo) < 0)
        {
            printf("GET_VSCREENINFO failed!\n");
            goto Error;
        }
        stVarInfo.transp = s_a32;
        stVarInfo.red = s_r32;
        stVarInfo.green = s_g32;
        stVarInfo.blue = s_b32;
        stVarInfo.bits_per_pixel = 32;
        stVarInfo.activate = FB_ACTIVATE_NOW;
        stVarInfo.xres = SCREEN_WIDTH;
        stVarInfo.yres = SCREEN_HEIGHT;
        stVarInfo.xres_virtual = SCREEN_WIDTH;
        stVarInfo.yres_virtual = SCREEN_HEIGHT * 2;
        if (ioctl(fd, FBIOPUT_VSCREENINFO, &stVarInfo) < 0)
        {
            printf("PUT_VSCREENINFO failed!\n");
            goto Error;
        }
        stLayerInfo.BufMode = HIFB_LAYER_BUF_ONE;
        stLayerInfo.u32Mask = HIFB_LAYERMASK_BUFMODE;
        if (ioctl(fd, FBIOPUT_LAYER_INFO, &stLayerInfo) < 0)
        {
            printf("PUT_LAYER_INFO failed!\n");
            goto Error;
        }
        if (ioctl(fd, FBIOPUT_SHOW_HIFB, &bShow) < 0)
        {
            printf("FBIOPUT_SHOW_HIFB failed!\n");
            goto Error;
        }
        fbp = (unsigned char *)mmap(0, 1920 * 1080 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        return HI_SUCCESS;
    Error:
        close(fd);
        return HI_FAILURE;
    }

//=======================================================================================================
//启动VO                            本文夹下的main.c文件内调用--------------------- [main.c step 2.5.0]
//=======================================================================================================
HI_S32 SAMPLE_COMM_VO_StartVO(SAMPLE_VO_CONFIG_S *pstVoConfig) // For  HDMIBOX
{
    // VO的属性配置
    VO_PUB_ATTR_S stVoPubAttr = {0};
    VO_VIDEO_LAYER_ATTR_S stLayerAttr = {0};
    VO_CHN_ATTR_S stChnAttr;
    VO_CSC_S               stVideoCSC     = {0};
    HI_HDMI_ATTR_S stHdmiAttr;
    hdmi_disp_mode = read_osd_parameter_key("Option", "display_set", 1);
    hdmi_size = read_osd_parameter_key("Option", "Size", 3);
    stVoPubAttr.enIntfType = pstVoConfig->enVoIntfType;
    stVoPubAttr.enIntfSync = pstVoConfig->enIntfSync;
    stVoPubAttr.u32BgColor = pstVoConfig->u32BgColor;

    //========================================================================================================================
    //配置HDMI输出属性

    CHECK_RET(HI_MPI_VO_SetPubAttr(pstVoConfig->VoDev, &stVoPubAttr), "HI_MPI_VO_SetPubAttr(0)");
    CHECK_RET(HI_MPI_VO_Enable(pstVoConfig->VoDev), "HI_MPI_VO_Enable(0)");
    
    // QT画布的起始点
    stLayerAttr.stDispRect.s32X = 0; 
    stLayerAttr.stDispRect.s32Y = 0;
   
    // HDMI屏显示图层的大小，屏的分辨率,
    switch(hdmi_disp_mode)
    {
        case HDMI_1080P:
            stLayerAttr.stDispRect.u32Width   = 1920;
            stLayerAttr.stDispRect.u32Height  = 1080;
            stLayerAttr.stImageSize.u32Width  = 1920;
            stLayerAttr.stImageSize.u32Height = 1080;
        break;
        case HDMI_1920x1200:
            stLayerAttr.stDispRect.u32Width   = 1920;
            stLayerAttr.stDispRect.u32Height  = 1200;
            stLayerAttr.stImageSize.u32Width  = 1920;
            stLayerAttr.stImageSize.u32Height = 1200;
        break;
    }
    stLayerAttr.u32DispFrmRt = 60;
    stLayerAttr.bClusterMode = HI_FALSE;
    stLayerAttr.bDoubleFrame = HI_FALSE;
    stLayerAttr.enPixFormat = pstVoConfig->enPixFormat;
    stLayerAttr.enDstDynamicRange = pstVoConfig->enDstDynamicRange;
    if (pstVoConfig->u32DisBufLen)
        CHECK_RET(HI_MPI_VO_SetDisplayBufLen(pstVoConfig->VoDev, pstVoConfig->u32DisBufLen), "HI_MPI_VO_SetDisplayBufLen(0)");
    if (VO_PART_MODE_MULTI == pstVoConfig->enVoPartMode)
        CHECK_RET(HI_MPI_VO_SetVideoLayerPartitionMode(pstVoConfig->VoDev, pstVoConfig->enVoPartMode), "HI_MPI_VO_SetVideoLayerPartitionMode(0)");
    CHECK_RET(HI_MPI_VO_SetVideoLayerAttr(pstVoConfig->VoDev, &stLayerAttr), "HI_MPI_VO_SetVideoLayerAttr(0)");
    CHECK_RET(HI_MPI_VO_EnableVideoLayer(pstVoConfig->VoDev), "HI_MPI_VO_EnableVideoLayer(0)");
    CHECK_RET(HI_MPI_VO_GetVideoLayerCSC(pstVoConfig->VoDev, &stVideoCSC), "HI_MPI_VO_GetVideoLayerCSC(0)");

    //2023-05-25 
    int connect_device  = GetIniKeyInt("Option","connect_device",   PARAM_FILE);    //1=OV6946,2=OS01A
    if(connect_device == 1)
    {
        stVideoCSC.enCscMatrix =VO_CSC_MATRIX_IDENTITY;         //edwin-2022-10-25
        stVideoCSC.u32Contrast  = read_osd_parameter_key("isp","sdcsc_constrast",60);                //对比度 [0,100]--edwin
        stVideoCSC.u32Hue       = read_osd_parameter_key("isp","sdcsc_hue",50);                      //色调  [0,100]--edwin
        stVideoCSC.u32Luma      = read_osd_parameter_key("isp","sdcsc_brightness",50);               //亮度 [0,100]--edwin
        stVideoCSC.u32Satuature = read_osd_parameter_key("isp","sdcsc_saturation",50);               //饱和度 [0,100]--edwin
    }
    if(connect_device == 2)
    {
        stVideoCSC.enCscMatrix =VO_CSC_MATRIX_IDENTITY;         //edwin-2022-10-25
        stVideoCSC.u32Contrast  = read_osd_parameter_key("isp","hdcsc_constrast",60);                //对比度 [0,100]--edwin
        stVideoCSC.u32Hue       = read_osd_parameter_key("isp","hdcsc_hue",50);                      //色调  [0,100]--edwin
        stVideoCSC.u32Luma      = read_osd_parameter_key("isp","hdcsc_brightness",50);               //亮度 [0,100]--edwin
        stVideoCSC.u32Satuature = read_osd_parameter_key("isp","hdcsc_saturation",50);               //饱和度 [0,100]--edwin
    }

    CHECK_RET(HI_MPI_VO_SetVideoLayerCSC(pstVoConfig->VoDev, &stVideoCSC), "HI_MPI_VO_SetVideoLayerCSC(0)");

    if(stViConfig.astViInfo[0].stDevInfo.ViDev == 0)
    {
        if(hdmi_size <3)
            hdmi_size = 3;          //if camera is os01a ,then make the hdmi_size to be 800x800
        mppOsdInit();
    }
    switch(hdmi_disp_mode)
    {
        case HDMI_1080P:
            switch (hdmi_size)      //视频流的大小设置，HDMI模块（VO通道内)有缩放功能, 与VI 通道内的图像长宽参数独立。
            {
            case 1:
                stChnAttr.stRect.s32X = 760;
                stChnAttr.stRect.s32Y = 340;
                stChnAttr.stRect.u32Width = 400;
                stChnAttr.stRect.u32Height = 400;
                break;
            case 2:
                stChnAttr.stRect.s32X = 660;
                stChnAttr.stRect.s32Y = 240;
                stChnAttr.stRect.u32Width = 600;
                stChnAttr.stRect.u32Height = 600;
                break;
            case 3:
                stChnAttr.stRect.s32X = 560;
                stChnAttr.stRect.s32Y = 140;
                stChnAttr.stRect.u32Width = 800;
                stChnAttr.stRect.u32Height = 800;
                break;
            case 4:
                stChnAttr.stRect.s32X = 560;
                stChnAttr.stRect.s32Y = 40;
                stChnAttr.stRect.u32Width = 1000;
                stChnAttr.stRect.u32Height = 1000;
                break;
            default:
                break;
            }
        break;
        case HDMI_1920x1200:
            switch (hdmi_size) //视频流的大小设置，HDMI模块（VO通道内)有缩放功能, 与VI 通道内的图像长宽参数独立。
            {
            case 1:
                stChnAttr.stRect.s32X = 760;
                stChnAttr.stRect.s32Y = 340;
                stChnAttr.stRect.u32Width = 400;
                stChnAttr.stRect.u32Height = 400;
                break;
            case 2:
                stChnAttr.stRect.s32X = 660;
                stChnAttr.stRect.s32Y = 240;
                stChnAttr.stRect.u32Width = 600;
                stChnAttr.stRect.u32Height = 600;
                break;
            case 3:
                stChnAttr.stRect.s32X = 560;
                stChnAttr.stRect.s32Y = 140;
                stChnAttr.stRect.u32Width = 800;
                stChnAttr.stRect.u32Height = 800;
                break;
            case 4:
                stChnAttr.stRect.s32X = 560;
                stChnAttr.stRect.s32Y = 40;
                stChnAttr.stRect.u32Width = 1000;
                stChnAttr.stRect.u32Height = 1000;
                break;
            default:
                break;
            }
        break;

    }
    PutIniKeyInt("Option","Size", hdmi_size,PARAM_FILE);
    printf("Display Size: %d * %d\n", stLayerAttr.stImageSize.u32Width, stLayerAttr.stImageSize.u32Height);
    printf("Image   Size: %d * %d\n",stChnAttr.stRect.u32Width ,stChnAttr.stRect.u32Height);
    stChnAttr.u32Priority = 0;
    stChnAttr.bDeflicker = HI_FALSE; //关闭视频抗闪烁
    HI_MPI_VO_SetChnAttr(pstVoConfig->VoDev, 0, &stChnAttr);
    HI_MPI_VO_EnableChn(pstVoConfig->VoDev, 0);
    // HI_MPI_VO_SetChnRotation(pstVoConfig->VoDev,0,ROTATION_180);

    //*********************************************************************************************************************
    // Start hdmi device.             Note : do this after vo device started.
    //*********************************************************************************************************************
    if (VO_INTF_HDMI & pstVoConfig->enVoIntfType)
    {
        CHECK_RET(HI_MPI_HDMI_Init(), "HI_MPI_HDMI_Init");
        CHECK_RET(HI_MPI_HDMI_Open(HI_HDMI_ID_0), "HI_MPI_HDMI_Open");
        CHECK_RET(HI_MPI_HDMI_GetAttr(HI_HDMI_ID_0, &stHdmiAttr), "HI_MPI_HDMI_GetAttr");
        stHdmiAttr.bEnableHdmi = HI_TRUE;                // TRUE=强制 HDMI 输出；FALSE=DVI 输出;
        stHdmiAttr.bEnableVideo = HI_TRUE;               // TRUE=输出正常图像；   FALSE=输出黑屏
        switch(hdmi_disp_mode)
        {
            case HDMI_1080P:     
                stHdmiAttr.enVideoFmt = HI_HDMI_VIDEO_FMT_1080P_60; break;
            case 
                HDMI_1920x1200: stHdmiAttr.enVideoFmt = HI_HDMI_VIDEO_FMT_VESA_1920X1200_60; break;
        }
        stHdmiAttr.enVidOutMode = HI_HDMI_VIDEO_MODE_RGB444;//HI_HDMI_VIDEO_MODE_YCBCR444;   // HDMI输出的色彩空间
        switch (pstVoConfig->enDstDynamicRange)
        {
            case DYNAMIC_RANGE_SDR8: 
                stHdmiAttr.enDeepColorMode = HI_HDMI_DEEP_COLOR_24BIT; break;
            case DYNAMIC_RANGE_HDR10:
                stHdmiAttr.enVidOutMode = HI_HDMI_VIDEO_MODE_RGB444  ; break;       //HI_HDMI_VIDEO_MODE_YCBCR422
            default: 
                stHdmiAttr.enDeepColorMode = HI_HDMI_DEEP_COLOR_24BIT;  break;
        }
        stHdmiAttr.bxvYCCMode = HI_FALSE;
        stHdmiAttr.enOutCscQuantization = HDMI_QUANTIZATION_LIMITED_RANGE;
        stHdmiAttr.bEnableAudio = HI_FALSE;                                     //是否使能音频
        stHdmiAttr.enSoundIntf = HI_HDMI_SND_INTERFACE_I2S;                     // HDMI 音频来源
        stHdmiAttr.bIsMultiChannel = HI_FALSE;                                  // 0=立体声;1=多声道
        stHdmiAttr.enBitDepth = HI_HDMI_BIT_DEPTH_16;                           //音频位宽
        stHdmiAttr.bEnableAviInfoFrame = HI_TRUE;
        stHdmiAttr.bEnableAudInfoFrame = HI_TRUE;
        stHdmiAttr.bEnableSpdInfoFrame = HI_FALSE;
        stHdmiAttr.bEnableMpegInfoFrame = HI_FALSE;
        stHdmiAttr.bDebugFlag = HI_FALSE;
        stHdmiAttr.bHDCPEnable = HI_FALSE;
        stHdmiAttr.b3DEnable = HI_FALSE;
        stHdmiAttr.enDefaultMode = HI_HDMI_FORCE_HDMI;
        CHECK_RET(HI_MPI_HDMI_SetAttr(HI_HDMI_ID_0, &stHdmiAttr), "HI_MPI_HDMI_SetAttr");
        CHECK_RET(HI_MPI_HDMI_Start(HI_HDMI_ID_0), "HI_MPI_HDMI_Start");
        mppVoHdmiCreateFb(); //创建HDMI显示的freambuffer

        //===============================================================================================
        //GET EDID---------------------2023-02-22
        //HI_HDMI_EDID_S              stEdidData;
        //HI_HDMI_SINK_CAPABILITY_S   stSinkCap;
        //sleep(2);                                                           //2秒延时处理
        //HI_MPI_HDMI_Force_GetEDID(0, &stEdidData);                          // 获取 EDID 
        //sleep(2);
        //HI_MPI_HDMI_GetSinkCapability(HI_HDMI_ID_0,&stSinkCap);             //获取能力集合
        //printf("====>GET EDID INFO:: bEdidValid=%d; u32Edidlength=%d\n", stEdidData.bEdidValid,stEdidData.u32Edidlength);
        //GET EDID---------------------2023-02-22
        //===============================================================================================

    }
    return HI_SUCCESS;
}

//============================================================================================
// Change VO
//=======================================================================================================
HI_S32 mppChangeVo(SAMPLE_VO_CONFIG_S *pstVoConfig, int mode)
    {
        VO_PUB_ATTR_S stVoPubAttr = {0};
        VO_VIDEO_LAYER_ATTR_S stLayerAttr;
        VO_CHN_ATTR_S stChnAttr;
        // VO_PUB_ATTR_S          stVoPubAttr    = {0};
        // VO_VIDEO_LAYER_ATTR_S  stLayerAttr    = {0};
        // VO_CHN_ATTR_S          stChnAttr;
        // VO_CSC_S               stVideoCSC     = {0};
        HI_HDMI_ATTR_S stHdmiAttr;
        // HI_S32                 fd;

        HI_MPI_HDMI_Stop(HI_HDMI_ID_0);
        HI_MPI_HDMI_Close(HI_HDMI_ID_0);
        HI_MPI_HDMI_DeInit();
        CHECK_RET(HI_MPI_VO_DisableChn(pstVoConfig->VoDev, 0), "HI_MPI_VO_DisableChn(0)");
        CHECK_RET(HI_MPI_VO_DisableVideoLayer(pstVoConfig->VoDev), "HI_MPI_VO_DisableVideoLayer(0)");
        CHECK_RET(HI_MPI_VO_Disable(pstVoConfig->VoDev), "HI_MPI_VO_Disable(0)");

        stVoPubAttr.enIntfType = pstVoConfig->enVoIntfType;
        stVoPubAttr.enIntfSync = pstVoConfig->enIntfSync;
        stVoPubAttr.u32BgColor = pstVoConfig->u32BgColor;
        CHECK_RET(HI_MPI_VO_SetPubAttr(pstVoConfig->VoDev, &stVoPubAttr), "HI_MPI_VO_SetPubAttr(0)");
        CHECK_RET(HI_MPI_VO_Enable(pstVoConfig->VoDev), "HI_MPI_VO_Enable(0)");
        stLayerAttr.stDispRect.s32X = 0; 
        stLayerAttr.stDispRect.s32Y = 0;

        // HDMI屏显示图层的大小，屏的分辨率,
        stLayerAttr.stDispRect.u32Width = 1920;   // 1920;        //显示总宽度//1280;//1920
        stLayerAttr.stDispRect.u32Height = 1080;  // 1080;        //显示总高度//720;//180
        stLayerAttr.u32DispFrmRt = 60;            //帧率
        stLayerAttr.stImageSize.u32Width = 1920;  // 1920;        //stLayerAttr.stDispRect.u32Width;
        stLayerAttr.stImageSize.u32Height = 1080; // 1080;        //stLayerAttr.stDispRect.u32Height;
        stLayerAttr.bClusterMode = HI_FALSE;
        stLayerAttr.bDoubleFrame = HI_FALSE;
        stLayerAttr.enPixFormat = pstVoConfig->enPixFormat;
        stLayerAttr.enDstDynamicRange = pstVoConfig->enDstDynamicRange;

        if (pstVoConfig->u32DisBufLen)
        {
            CHECK_RET(HI_MPI_VO_SetDisplayBufLen(pstVoConfig->VoDev, pstVoConfig->u32DisBufLen), "HI_MPI_VO_SetDisplayBufLen(0)");
        }
        if (VO_PART_MODE_MULTI == pstVoConfig->enVoPartMode)
        {
            CHECK_RET(HI_MPI_VO_SetVideoLayerPartitionMode(pstVoConfig->VoDev, pstVoConfig->enVoPartMode), "HI_MPI_VO_SetVideoLayerPartitionMode(0)");
        }
        CHECK_RET(HI_MPI_VO_SetVideoLayerAttr(pstVoConfig->VoDev, &stLayerAttr), "HI_MPI_VO_SetVideoLayerAttr(0)");
        CHECK_RET(HI_MPI_VO_EnableVideoLayer(pstVoConfig->VoDev), "HI_MPI_VO_EnableVideoLayer(0)");

        switch (mode) //视频流的大小设置，HDMI模块（VO通道内)有缩放功能, 与VI 通道内的图像长宽参数独立。
        {
        case 0:
            stChnAttr.stRect.s32X = 760;
            stChnAttr.stRect.s32Y = 340;
            stChnAttr.stRect.u32Width = 400;
            stChnAttr.stRect.u32Height = 400;
            break;
        case 1:
            stChnAttr.stRect.s32X = 660;
            stChnAttr.stRect.s32Y = 240;
            stChnAttr.stRect.u32Width = 600;
            stChnAttr.stRect.u32Height = 600;
            break;
        case 2:
            stChnAttr.stRect.s32X = 560;
            stChnAttr.stRect.s32Y = 140;
            stChnAttr.stRect.u32Width = 800;
            stChnAttr.stRect.u32Height = 800;
            break;
        case 3:
            stChnAttr.stRect.s32X = 420;
            stChnAttr.stRect.s32Y = 0;
            stChnAttr.stRect.u32Width = 1000;
            stChnAttr.stRect.u32Height = 1000;
            break;
        default:
            break;
        }
        printf("Display Size: %d * %d\n", stLayerAttr.stImageSize.u32Width, stLayerAttr.stImageSize.u32Height);
        stChnAttr.u32Priority = 0;
        stChnAttr.bDeflicker = HI_FALSE; //关闭视频抗闪烁

        HI_MPI_VO_SetChnAttr(pstVoConfig->VoDev, 0, &stChnAttr);
        HI_MPI_VO_EnableChn(pstVoConfig->VoDev, 0);
        CHECK_RET(HI_MPI_HDMI_Init(), "HI_MPI_HDMI_Init");
        CHECK_RET(HI_MPI_HDMI_Open(HI_HDMI_ID_0), "HI_MPI_HDMI_Open");
        CHECK_RET(HI_MPI_HDMI_GetAttr(HI_HDMI_ID_0, &stHdmiAttr), "HI_MPI_HDMI_GetAttr");
        stHdmiAttr.bEnableHdmi = HI_TRUE;                                                                                // TRUE=强制 HDMI 输出；FALSE=DVI 输出;
        stHdmiAttr.bEnableVideo = HI_TRUE;                                                                               // TRUE=输出正常图像；   FALSE=输出黑屏
        stHdmiAttr.enVideoFmt = (hdmi_disp_mode == HDMI_1080P) ? HI_HDMI_VIDEO_FMT_1080P_60 : HI_HDMI_VIDEO_FMT_720P_60; // HDMI输出总尺寸及帧率
        stHdmiAttr.enVidOutMode = HI_HDMI_VIDEO_MODE_RGB444;//HI_HDMI_VIDEO_MODE_RGB444;//HI_HDMI_VIDEO_MODE_YCBCR444;                                                           // HDMI输出的色彩空间
        switch (pstVoConfig->enDstDynamicRange)
        {
        case DYNAMIC_RANGE_SDR8:
            stHdmiAttr.enDeepColorMode = HI_HDMI_DEEP_COLOR_24BIT;
            break;
        case DYNAMIC_RANGE_HDR10:
            stHdmiAttr.enVidOutMode = HI_HDMI_VIDEO_MODE_RGB444;//HI_HDMI_VIDEO_MODE_YCBCR422;
            break;
        default:
            stHdmiAttr.enDeepColorMode = HI_HDMI_DEEP_COLOR_24BIT; // DeepColor 输出模式
            break;
        }
        stHdmiAttr.bxvYCCMode = HI_FALSE;
        stHdmiAttr.enOutCscQuantization = HDMI_QUANTIZATION_LIMITED_RANGE;
        stHdmiAttr.bEnableAudio = HI_FALSE;                 //是否使能音频
        stHdmiAttr.enSoundIntf = HI_HDMI_SND_INTERFACE_I2S; // HDMI 音频来源
        stHdmiAttr.bIsMultiChannel = HI_FALSE;              // 0=立体声;1=多声道
        stHdmiAttr.enBitDepth = HI_HDMI_BIT_DEPTH_16;       //音频位宽
        stHdmiAttr.bEnableAviInfoFrame = HI_TRUE;
        stHdmiAttr.bEnableAudInfoFrame = HI_TRUE;
        stHdmiAttr.bEnableSpdInfoFrame = HI_FALSE;
        stHdmiAttr.bEnableMpegInfoFrame = HI_FALSE;
        stHdmiAttr.bDebugFlag = HI_FALSE;
        stHdmiAttr.bHDCPEnable = HI_FALSE;
        stHdmiAttr.b3DEnable = HI_FALSE;
        stHdmiAttr.enDefaultMode = HI_HDMI_FORCE_HDMI;
        CHECK_RET(HI_MPI_HDMI_SetAttr(HI_HDMI_ID_0, &stHdmiAttr), "HI_MPI_HDMI_SetAttr");
        CHECK_RET(HI_MPI_HDMI_Start(HI_HDMI_ID_0), "HI_MPI_HDMI_Start");
        mppVoHdmiCreateFb(); //创建HDMI显示的freambuffer

        return HI_SUCCESS;
    }

//=======================================================================================================
// VO_StopVO
//=======================================================================================================
HI_S32 SAMPLE_COMM_VO_StopVO(SAMPLE_VO_CONFIG_S *pstVoConfig)
{
    if (VO_INTF_HDMI & pstVoConfig->enVoIntfType)
    {
        HI_MPI_HDMI_Stop(HI_HDMI_ID_0);
        HI_MPI_HDMI_Close(HI_HDMI_ID_0);
        HI_MPI_HDMI_DeInit();
    }
    CHECK_RET(HI_MPI_VO_DisableChn(pstVoConfig->VoDev, 0), "HI_MPI_VO_DisableChn(0)");
    CHECK_RET(HI_MPI_VO_DisableVideoLayer(pstVoConfig->VoDev), "HI_MPI_VO_DisableVideoLayer(0)");
    CHECK_RET(HI_MPI_VO_Disable(pstVoConfig->VoDev), "HI_MPI_VO_Disable(0)");
    return HI_SUCCESS;
}

//=======================================================================================================
// VENC_SaveStream
//=======================================================================================================
HI_S32 SAMPLE_COMM_VENC_SaveStream(FILE *pFd, VENC_STREAM_S *pstStream)
{
    HI_S32 i;
    for (i = 0; i < pstStream->u32PackCount; i++)
    {
        fwrite(pstStream->pstPack[i].pu8Addr + pstStream->pstPack[i].u32Offset,
                pstStream->pstPack[i].u32Len - pstStream->pstPack[i].u32Offset, 1, pFd);

        fflush(pFd);
    }
    return HI_SUCCESS;
}


//=======================================================================================================
// create named fifo
//=======================================================================================================
HI_S32 SAMPLE_COMM_VENC_create_fifo(HI_CHAR * fifo_name)
{

}


//=======================================================================================================
// VENC_SaveStream
//=======================================================================================================
HI_S32 SAMPLE_COMM_VENC_SaveStream_fifo(HI_S32 fifo_fd, VENC_STREAM_S *pstStream)
{
    HI_S32 i;
    int ret = 0;
    for (i = 0; i < pstStream->u32PackCount; i++)
    {
        ret = write(fifo_fd, pstStream->pstPack[i].pu8Addr + pstStream->pstPack[i].u32Offset,
                pstStream->pstPack[i].u32Len - pstStream->pstPack[i].u32Offset);
        printf("========================>ret=%d,pstStream->pstPack[i].u32Offset=%d length=%d\n",ret,pstStream->pstPack[i].u32Offset,pstStream->pstPack[i].u32Len - pstStream->pstPack[i].u32Offset);
    }
    return HI_SUCCESS;
}

//=======================================================================================================
// VENC_SaveJpeg
//=======================================================================================================
HI_S32 SAMPLE_COMM_VENC_SaveJpeg(VENC_CHN VencChn, HI_U32 SnapCnt, char *path)
    {
        struct timeval TimeoutVal;
        fd_set read_fds;
        HI_S32 s32VencFd;
        VENC_CHN_STATUS_S stStat;
        VENC_STREAM_S stStream;
        HI_S32 s32Ret;
        HI_U32 i;
        s32VencFd = HI_MPI_VENC_GetFd(VencChn);
        if (s32VencFd < 0)
        {
            SAMPLE_PRT("HI_MPI_VENC_GetFd faild with%#x!\n", s32VencFd);
            return HI_FAILURE;
        }
        for (i = 0; i < SnapCnt; i++)
        {
            FD_ZERO(&read_fds);
            FD_SET(s32VencFd, &read_fds);
            TimeoutVal.tv_sec = 2;
            TimeoutVal.tv_usec = 0;
            s32Ret = select(s32VencFd + 1, &read_fds, NULL, NULL, &TimeoutVal);
            if (s32Ret < 0)
            {
                SAMPLE_PRT("snap select failed!\n");
                return HI_FAILURE;
            }
            else if (0 == s32Ret)
            {
                SAMPLE_PRT("snap time out!\n");
                return HI_FAILURE;
            }
            else
            {
                if (FD_ISSET(s32VencFd, &read_fds))
                {
                    s32Ret = HI_MPI_VENC_QueryStatus(VencChn, &stStat);
                    if (s32Ret != HI_SUCCESS)
                    {
                        SAMPLE_PRT("HI_MPI_VENC_QueryStatus failed with %#x!\n", s32Ret);
                        return HI_FAILURE;
                    }
                    /*******************************************************
                    suggest to check both u32CurPacks and u32LeftStreamFrames at the same time,for example:
                     if(0 == stStat.u32CurPacks || 0 == stStat.u32LeftStreamFrames)
                     {                SAMPLE_PRT("NOTE: Current  frame is NULL!\n");
                        return HI_SUCCESS;
                     }
                     *******************************************************/
                    if (0 == stStat.u32CurPacks)
                    {
                        SAMPLE_PRT("NOTE: Current  frame is NULL!\n");
                        return HI_SUCCESS;
                    }
                    stStream.pstPack = (VENC_PACK_S *)malloc(sizeof(VENC_PACK_S) * stStat.u32CurPacks);
                    if (NULL == stStream.pstPack)
                    {
                        SAMPLE_PRT("malloc memory failed!\n");
                        return HI_FAILURE;
                    }
                    stStream.u32PackCount = stStat.u32CurPacks;
                    s32Ret = HI_MPI_VENC_GetStream(VencChn, &stStream, -1);
                    if (HI_SUCCESS != s32Ret)
                    {
                        SAMPLE_PRT("HI_MPI_VENC_GetStream failed with %#x!\n", s32Ret);

                        free(stStream.pstPack);
                        stStream.pstPack = NULL;
                        return HI_FAILURE;
                    }
                    char acFile[FILE_NAME_LEN] = {0};
                    FILE *pFile;
                    time_t rawtime;
                    struct tm *info;
                    time(&rawtime);
                    info = localtime(&rawtime);
                    snprintf(acFile, FILE_NAME_LEN, "%s/%d-%02d-%02d-%02d-%02d-%02d.jpg", path,
                             1900 + info->tm_year, info->tm_mon + 1, info->tm_mday,
                             info->tm_hour, info->tm_min, info->tm_sec);
                    pFile = fopen(acFile, "wb");
                    if (pFile == NULL)
                    {
                        SAMPLE_PRT("open file err\n");

                        free(stStream.pstPack);
                        stStream.pstPack = NULL;
                        return HI_FAILURE;
                    }
                    s32Ret = SAMPLE_COMM_VENC_SaveStream(pFile, &stStream);
                    if (HI_SUCCESS != s32Ret)
                    {
                        SAMPLE_PRT("save snap picture failed!\n");

                        free(stStream.pstPack);
                        stStream.pstPack = NULL;

                        fclose(pFile);
                        return HI_FAILURE;
                    }

                    fclose(pFile);
                    s32Ret = HI_MPI_VENC_ReleaseStream(VencChn, &stStream);
                    if (HI_SUCCESS != s32Ret)
                    {
                        SAMPLE_PRT("HI_MPI_VENC_ReleaseStream failed with %#x!\n", s32Ret);

                        free(stStream.pstPack);
                        stStream.pstPack = NULL;

                        return HI_FAILURE;
                    }

                    free(stStream.pstPack);
                    stStream.pstPack = NULL;
                }
            }
        }

        return HI_SUCCESS;
    }
#if 0
HI_S32 HisiPutH265DataToBuffer(VENC_STREAM_S *pstStream)
{
	HI_S32 i,j,x;
	HI_S32 len=0,off=0,len2=2,uplen=0;
	unsigned char *pstr;
	int iframe=0;
	for (i = 0; i < pstStream->u32PackCount; i++)
	{
		len+=pstStream->pstPack[i].u32Len;
	}
	if(len>=400*1024)
	{
		printf("drop data %d\n",len);
		return HI_SUCCESS;
	}

    if(n<NMAX)
    {
		for (i = 0; i < pstStream->u32PackCount; i++)
		{
			memcpy(ringfifo[iput].buffer+off,pstStream->pstPack[i].pu8Addr,pstStream->pstPack[i].u32Len);
			off+=pstStream->pstPack[i].u32Len;
			pstr=pstStream->pstPack[i].pu8Addr;
			switch(pstr[4])
			{
				case 0x40:
					UpdateVps(pstr+4,pstStream->pstPack[i].u32Len-4);
					break;
				case 0x42:
					UpdateSps(pstr+4,pstStream->pstPack[i].u32Len-4);
					break;
				case 0x44:
					UpdatePps(pstr+4,pstStream->pstPack[i].u32Len-4);//NAL_UNIT_PPS, 34
					break;
				case 0x4e:
					UpdateSei(pstr+4,pstStream->pstPack[i].u32Len-4);
					break;
				case 0x26:
					ringfifo[iput].frame_type=FRAME_TYPE_I;
					break;
				case 0x02:
					ringfifo[iput].frame_type = FRAME_TYPE_P;
					break;
			}

		}

        ringfifo[iput].size= len;

        iput = addring(iput);
//		printf("(%d)",iput);
//		fflush(stdout);
        n++;
    }

	return HI_SUCCESS;
}
#endif
//=======================================================================================================
// VENC_GetVencStreamProc
//=======================================================================================================
HI_VOID *SAMPLE_COMM_VENC_GetVencStreamProc(HI_VOID *p)
    {
        SAMPLE_VENC_GETSTREAM_PARA_S *pstPara;
        struct timeval TimeoutVal;
        fd_set read_fds;
        HI_S32 VencFd;
        HI_CHAR aszFileName[64];
        HI_CHAR aszMp4Name[64];

        HI_S32 fifo_fd;
        VENC_CHN_STATUS_S stStat;
        VENC_STREAM_S stStream;
        HI_S32 s32Ret;
        prctl(PR_SET_NAME, "GetVencStream", 0, 0, 0);
        pstPara = (SAMPLE_VENC_GETSTREAM_PARA_S *)p;
        time_t rawtime;
        struct tm *info;

        time(&rawtime);
        info = localtime(&rawtime);
        //fifo_fd = SAMPLE_COMM_VENC_create_fifo(gs_stPara.path);
        /* Set Venc Fd. */
        VencFd = HI_MPI_VENC_GetFd(0);
        if (VencFd < 0)
        {
            SAMPLE_PRT("HI_MPI_VENC_GetFd failed with %#x!\n",
                       VencFd);
            return NULL;
        }

        /******************************************
         step 2:  Start to get streams of each channel.
        ******************************************/
        while (HI_TRUE == pstPara->bThreadStart)
        {
            FD_ZERO(&read_fds);
            FD_SET(VencFd, &read_fds);
            TimeoutVal.tv_sec = 2;
            TimeoutVal.tv_usec = 0;
            s32Ret = select(VencFd + 1, &read_fds, NULL, NULL, &TimeoutVal);
            if (s32Ret < 0)
            {
                SAMPLE_PRT("select failed!\n");
                break;
            }
            else if (s32Ret == 0)
            {
                SAMPLE_PRT("get venc stream time out, exit thread\n");
                continue;
            }
            else
            {
                /*******************************************************
                 step 2.1 : query how many packs in one-frame stream.
                *******************************************************/
                memset(&stStream, 0, sizeof(stStream));
                s32Ret = HI_MPI_VENC_QueryStatus(0, &stStat);
                if (HI_SUCCESS != s32Ret)
                {
                    SAMPLE_PRT("HI_MPI_VENC_QueryStatus chn[] failed with %#x!\n", s32Ret);
                    break;
                }
                if (0 == stStat.u32CurPacks)
                {
                    SAMPLE_PRT("NOTE: Current  frame is NULL!\n");
                    continue;
                }
                /*******************************************************
                 step 2.3 : malloc corresponding number of pack nodes.
                *******************************************************/
                stStream.pstPack = (VENC_PACK_S *)malloc(sizeof(VENC_PACK_S) * stStat.u32CurPacks);
                if (NULL == stStream.pstPack)
                {
                    SAMPLE_PRT("malloc stream pack failed!\n");
                    break;
                }

                /*******************************************************
                 step 2.4 : call mpi to get one-frame stream
                *******************************************************/
                stStream.u32PackCount = stStat.u32CurPacks;
                s32Ret = HI_MPI_VENC_GetStream(0, &stStream, HI_TRUE);
                if (HI_SUCCESS != s32Ret)
                {
                    free(stStream.pstPack);
                    stStream.pstPack = NULL;
                    SAMPLE_PRT("HI_MPI_VENC_GetStream failed with %#x!\n",
                               s32Ret);
                    break;
                }
                //s32Ret = SAMPLE_COMM_VENC_SaveStream(pFile, &stStream);

//=================dzq=========================
//copy stream to shared memory
//write stream to named fifo
//=================dzq [end]===================
                //SAMPLE_COMM_VENC_SaveStream_fifo(fifo_fd, &stStream);

                 struct timeval end;
                //if (VencChn == 1)
                {
                    HisiPutH265DataToBuffer(&stStream);
                    float time_use=0;
                    static struct timeval start;
                    gettimeofday(&end,NULL);
                    time_use=((end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec))/1000;//ms
                    gettimeofday(&start,NULL); //gettimeofday(&start,&tz);结果一样
                    //printf("time_use is %fms\n",time_use);
                }

                if (HI_SUCCESS != s32Ret)
                {
                    free(stStream.pstPack);
                    stStream.pstPack = NULL;
                    SAMPLE_PRT("save stream failed!\n");
                    break;
                }
                /*******************************************************
                 step 2.6 : release stream
                 *******************************************************/
                s32Ret = HI_MPI_VENC_ReleaseStream(0, &stStream);
                if (HI_SUCCESS != s32Ret)
                {
                    SAMPLE_PRT("HI_MPI_VENC_ReleaseStream failed!\n");
                    free(stStream.pstPack);
                    stStream.pstPack = NULL;
                    break;
                }

                /*******************************************************
                 step 2.7 : free pack nodes
                *******************************************************/
                free(stStream.pstPack);
                stStream.pstPack = NULL;
            }
        }
#if 0
    system("sync");
    sprintf(cmd,"/usr/bin/MP4Box -add %s %s -inter 500",aszFileName,aszMp4Name);
    system(cmd);
    system("sync");
    sprintf(cmd,"rm %s -f",aszFileName);
    system(cmd);
    system("sync");
#endif
        return NULL;
    }

//=======================================================================================================
// VENC_Start
//=======================================================================================================
HI_S32 SAMPLE_COMM_VENC_Start(PAYLOAD_TYPE_E enType, SIZE_S stSize, HI_U32 u32FrameRate, VPSS_CHN VpssChn, VENC_CHN VencChn,
                                  HI_U32 u32Profile, HI_BOOL bRcnRefShareBuf, VENC_GOP_ATTR_S *pstGopAttr, char *path)
    {
        VENC_RECV_PIC_PARAM_S       stRecvParam;
        VENC_CHN_ATTR_S             stVencChnAttr;
        VENC_ATTR_JPEG_S            stJpegAttr;
        VENC_H265_FIXQP_S           stH265FixQp;
        VENC_MJPEG_FIXQP_S          stMjpegeFixQp;
        MPP_CHN_S                   stSrcChn;
        MPP_CHN_S                   stDestChn;

        /******************************************
         step 1:  Create Venc Channel
        ******************************************/
        stVencChnAttr.stVencAttr.enType             = enType;
        stVencChnAttr.stVencAttr.u32MaxPicWidth     = stSize.u32Width;
        stVencChnAttr.stVencAttr.u32MaxPicHeight    = stSize.u32Height;
        stVencChnAttr.stVencAttr.u32PicWidth        = stSize.u32Width;                       /*the picture width*/
        stVencChnAttr.stVencAttr.u32PicHeight       = stSize.u32Height;                     /*the picture height*/
        stVencChnAttr.stVencAttr.u32BufSize         = stSize.u32Width * stSize.u32Height * 2; /*stream buffer size*/
        stVencChnAttr.stVencAttr.u32Profile         = u32Profile;
        stVencChnAttr.stVencAttr.bByFrame           = HI_TRUE; /*get stream mode is slice mode or frame mode?*/
        switch (enType)
        {
        case PT_H265:
            stVencChnAttr.stRcAttr.enRcMode                 = VENC_RC_MODE_H265FIXQP;
            stH265FixQp.u32Gop                              = 30;                   //Range:[1, 65536]; the interval of ISLICE. 
            stH265FixQp.u32SrcFrameRate                     = u32FrameRate;
            stH265FixQp.fr32DstFrameRate                    = u32FrameRate;
            stH265FixQp.u32IQp                              = 25;                   //Range:[0, 51]; qp of the I frame 
            stH265FixQp.u32PQp                              = 30;                   //Range:[0, 51]; qp of the P frame 
            stH265FixQp.u32BQp                              = 32;                   //Range:[0, 51]; qp of the B frame 
            memcpy(&stVencChnAttr.stRcAttr.stH265FixQp, &stH265FixQp, sizeof(VENC_H265_FIXQP_S));
            stVencChnAttr.stVencAttr.stAttrH265e.bRcnRefShareBuf = bRcnRefShareBuf;
            memcpy(&stVencChnAttr.stGopAttr, pstGopAttr, sizeof(VENC_GOP_ATTR_S));
            break;

        case PT_MJPEG:
            stVencChnAttr.stRcAttr.enRcMode                 = VENC_RC_MODE_MJPEGFIXQP;
            stMjpegeFixQp.u32Qfactor                        = 95;
            stMjpegeFixQp.u32SrcFrameRate                   = u32FrameRate;
            stMjpegeFixQp.fr32DstFrameRate                  = u32FrameRate;
            memcpy(&stVencChnAttr.stRcAttr.stMjpegFixQp, &stMjpegeFixQp, sizeof(VENC_MJPEG_FIXQP_S));
            stVencChnAttr.stGopAttr.enGopMode               = VENC_GOPMODE_NORMALP;
            stVencChnAttr.stGopAttr.stNormalP.s32IPQpDelta  = 0;
            break;

        case PT_JPEG:
            stJpegAttr.bSupportDCF                          = HI_FALSE;
            stJpegAttr.stMPFCfg.u8LargeThumbNailNum         = 0;
            stJpegAttr.enReceiveMode                        = VENC_PIC_RECEIVE_SINGLE;
            memcpy(&stVencChnAttr.stVencAttr.stAttrJpege, &stJpegAttr, sizeof(VENC_ATTR_JPEG_S));
            stVencChnAttr.stGopAttr.enGopMode               = VENC_GOPMODE_NORMALP;
            stVencChnAttr.stGopAttr.stNormalP.s32IPQpDelta  = 0;
            break;

        default:
            break;
        }
        CHECK_RET(HI_MPI_VENC_CreateChn(VencChn, &stVencChnAttr), "HI_MPI_VENC_CreateChn()");
        stRecvParam.s32RecvPicNum = -1;
        CHECK_RET(HI_MPI_VENC_StartRecvFrame(VencChn, &stRecvParam), "HI_MPI_VENC_StartRecvFrame()");
        stSrcChn.enModId = HI_ID_VPSS;
        stSrcChn.s32DevId = 0;
        stSrcChn.s32ChnId = VpssChn;
        stDestChn.enModId = HI_ID_VENC;
        stDestChn.s32DevId = 0;
        stDestChn.s32ChnId = VencChn;
        CHECK_RET(HI_MPI_SYS_Bind(&stSrcChn, &stDestChn), "HI_MPI_SYS_Bind(VPSS-VENC)");
        switch (enType)
        {
        case PT_H265:
            gs_stPara.bThreadStart = HI_TRUE;
            gs_stPara.s32Cnt = 1;
            gs_stPara.VeChn[0] = 0;
            memset(gs_stPara.path, 0, 50);
            memcpy(gs_stPara.path, path, strlen(path));
            pthread_create(&gs_VencPid, 0, SAMPLE_COMM_VENC_GetVencStreamProc, (HI_VOID *)&gs_stPara);
            break;
        case PT_JPEG:
            SAMPLE_COMM_VENC_SaveJpeg(0, 1, path);
            break;
        default:
            break;
        }
        return HI_SUCCESS;
    }

//============================================================================================
// VENC_Stop
//============================================================================================
HI_S32 SAMPLE_COMM_VENC_Stop(VPSS_CHN VpssChn)
    {
        MPP_CHN_S stSrcChn;
        MPP_CHN_S stDestChn;
        if (HI_TRUE == gs_stPara.bThreadStart)
        {
            gs_stPara.bThreadStart = HI_FALSE;
            pthread_join(gs_VencPid, 0);
        }
        stSrcChn.enModId = HI_ID_VPSS;
        stSrcChn.s32DevId = 0;
        stSrcChn.s32ChnId = VpssChn;
        stDestChn.enModId = HI_ID_VENC;
        stDestChn.s32DevId = 0;
        stDestChn.s32ChnId = 0;
        CHECK_RET(HI_MPI_SYS_UnBind(&stSrcChn, &stDestChn), "HI_MPI_SYS_UnBind(VPSS-VENC)");
        CHECK_RET(HI_MPI_VENC_StopRecvFrame(0), "HI_MPI_VENC_StopRecvFrame()");
        CHECK_RET(HI_MPI_VENC_DestroyChn(0), "HI_MPI_VENC_DestroyChn()");
        return HI_SUCCESS;
    }

//============================================================================================
//
#define PRINTF_VDEC_CHN_STATUS(Chn, stStatus)                                                                                                                                          \
    do                                                                                                                                                                                 \
    {                                                                                                                                                                                  \
        printf("\033[0;33m ---------------------------------------------------------------------------------------------------\033[0;39m\n");                                          \
        printf("\033[0;33m chn:%d, Type:%d, bStart:%d, DecodeFrames:%d, LeftPics:%d, LeftBytes:%d, LeftFrames:%d, RecvFrames:%d  \033[0;39m\n",                                        \
               Chn,                                                                                                                                                                    \
               stStatus.enType,                                                                                                                                                        \
               stStatus.bStartRecvStream,                                                                                                                                              \
               stStatus.u32DecodeStreamFrames,                                                                                                                                         \
               stStatus.u32LeftPics,                                                                                                                                                   \
               stStatus.u32LeftStreamBytes,                                                                                                                                            \
               stStatus.u32LeftStreamFrames,                                                                                                                                           \
               stStatus.u32RecvStreamFrames);                                                                                                                                          \
        printf("\033[0;33m FormatErr:%d,    s32PicSizeErrSet:%d,  s32StreamUnsprt:%d,  s32PackErr:%d,  u32PrtclNumErrSet:%d,  s32RefErrSet:%d,  s32PicBufSizeErrSet:%d  \033[0;39m\n", \
               stStatus.stVdecDecErr.s32FormatErr,                                                                                                                                     \
               stStatus.stVdecDecErr.s32PicSizeErrSet,                                                                                                                                 \
               stStatus.stVdecDecErr.s32StreamUnsprt,                                                                                                                                  \
               stStatus.stVdecDecErr.s32PackErr,                                                                                                                                       \
               stStatus.stVdecDecErr.s32PrtclNumErrSet,                                                                                                                                \
               stStatus.stVdecDecErr.s32RefErrSet,                                                                                                                                     \
               stStatus.stVdecDecErr.s32PicBufSizeErrSet);                                                                                                                             \
        printf("\033[0;33m ---------------------------------------------------------------------------------------------------\033[0;39m\n");                                          \
    } while (0)

//============================================================================================
// VDEC_InitVBPool
//============================================================================================
HI_S32 SAMPLE_COMM_VDEC_InitVBPool(HI_U32 ChnNum, SAMPLE_VDEC_ATTR *pastSampleVdec)
    {
        VB_CONFIG_S stVbConf;
        HI_S32 i, j, pos = 0, s32Ret;
        HI_BOOL bFindFlag;
        SAMPLE_VDEC_BUF astSampleVdecBuf[VDEC_MAX_CHN_NUM];
        memset(astSampleVdecBuf, 0, sizeof(SAMPLE_VDEC_BUF) * VDEC_MAX_CHN_NUM);
        memset(&stVbConf, 0, sizeof(VB_CONFIG_S));

        for (i = 0; i < ChnNum; i++)
        {
            astSampleVdecBuf[i].u32PicBufSize = VDEC_GetPicBufferSize(pastSampleVdec[i].enType, pastSampleVdec[i].u32Width, pastSampleVdec[i].u32Height,
                                                                      PIXEL_FORMAT_YVU_SEMIPLANAR_420, pastSampleVdec[i].stSapmleVdecVideo.enBitWidth, 0);
            astSampleVdecBuf[i].u32TmvBufSize = VDEC_GetTmvBufferSize(pastSampleVdec[i].enType, pastSampleVdec[i].u32Width, pastSampleVdec[i].u32Height);
        }

        /* PicBuffer */
        for (j = 0; j < VB_MAX_COMM_POOLS; j++)
        {
            bFindFlag = HI_FALSE;
            for (i = 0; i < ChnNum; i++)
            {
                if ((HI_FALSE == bFindFlag) && (0 != astSampleVdecBuf[i].u32PicBufSize) && (HI_FALSE == astSampleVdecBuf[i].bPicBufAlloc))
                {
                    stVbConf.astCommPool[j].u64BlkSize = astSampleVdecBuf[i].u32PicBufSize;
                    stVbConf.astCommPool[j].u32BlkCnt = pastSampleVdec[i].u32FrameBufCnt;
                    astSampleVdecBuf[i].bPicBufAlloc = HI_TRUE;
                    bFindFlag = HI_TRUE;
                    pos = j;
                }

                if ((HI_TRUE == bFindFlag) && (HI_FALSE == astSampleVdecBuf[i].bPicBufAlloc) && (stVbConf.astCommPool[j].u64BlkSize == astSampleVdecBuf[i].u32PicBufSize))
                {
                    stVbConf.astCommPool[j].u32BlkCnt += pastSampleVdec[i].u32FrameBufCnt;
                    astSampleVdecBuf[i].bPicBufAlloc = HI_TRUE;
                }
            }
        }

        /* TmvBuffer */
        for (j = pos + 1; j < VB_MAX_COMM_POOLS; j++)
        {
            bFindFlag = HI_FALSE;
            for (i = 0; i < ChnNum; i++)
            {
                if ((HI_FALSE == bFindFlag) && (0 != astSampleVdecBuf[i].u32TmvBufSize) && (HI_FALSE == astSampleVdecBuf[i].bTmvBufAlloc))
                {
                    stVbConf.astCommPool[j].u64BlkSize = astSampleVdecBuf[i].u32TmvBufSize;
                    stVbConf.astCommPool[j].u32BlkCnt = pastSampleVdec[i].stSapmleVdecVideo.u32RefFrameNum + 1;
                    astSampleVdecBuf[i].bTmvBufAlloc = HI_TRUE;
                    bFindFlag = HI_TRUE;
                    pos = j;
                }

                if ((HI_TRUE == bFindFlag) && (HI_FALSE == astSampleVdecBuf[i].bTmvBufAlloc) && (stVbConf.astCommPool[j].u64BlkSize == astSampleVdecBuf[i].u32TmvBufSize))
                {
                    stVbConf.astCommPool[j].u32BlkCnt += pastSampleVdec[i].stSapmleVdecVideo.u32RefFrameNum + 1;
                    astSampleVdecBuf[i].bTmvBufAlloc = HI_TRUE;
                }
            }
        }
        stVbConf.u32MaxPoolCnt = pos + 1;
        HI_MPI_VB_ExitModCommPool(VB_UID_VDEC);
        CHECK_RET(HI_MPI_VB_SetModPoolConfig(VB_UID_VDEC, &stVbConf), "HI_MPI_VB_SetModPoolConfigig");
        s32Ret = HI_MPI_VB_InitModCommPool(VB_UID_VDEC);
        if (HI_SUCCESS != s32Ret)
        {
            printf("HI_MPI_VB_InitModCommPool fail for 0x%x\n", s32Ret);
            HI_MPI_VB_ExitModCommPool(VB_UID_VDEC);
            return HI_FAILURE;
        }
        return HI_SUCCESS;
    }

//============================================================================================
// VDEC_Start
//============================================================================================
HI_S32 SAMPLE_COMM_VDEC_Start(HI_S32 s32ChnNum, SAMPLE_VDEC_ATTR *pastSampleVdec)
    {
        HI_S32 i;
        VDEC_CHN_ATTR_S stChnAttr[VDEC_MAX_CHN_NUM];
        VDEC_CHN_PARAM_S stChnParam;
        VDEC_MOD_PARAM_S stModParam;
        CHECK_RET(HI_MPI_VDEC_GetModParam(&stModParam), "HI_MPI_VDEC_GetModParam");
        stModParam.enVdecVBSource = VB_SOURCE_MODULE;
        CHECK_RET(HI_MPI_VDEC_SetModParam(&stModParam), "HI_MPI_VDEC_GetModParam");
        for (i = 0; i < s32ChnNum; i++)
        {
            stChnAttr[i].enType = pastSampleVdec[i].enType;
            stChnAttr[i].enMode = pastSampleVdec[i].enMode;
            stChnAttr[i].u32PicWidth = pastSampleVdec[i].u32Width;
            stChnAttr[i].u32PicHeight = pastSampleVdec[i].u32Height;
            stChnAttr[i].u32StreamBufSize = pastSampleVdec[i].u32Width * pastSampleVdec[i].u32Height;
            stChnAttr[i].u32FrameBufCnt = pastSampleVdec[i].u32FrameBufCnt;
            stChnAttr[i].stVdecVideoAttr.u32RefFrameNum = pastSampleVdec[i].stSapmleVdecVideo.u32RefFrameNum;
            stChnAttr[i].stVdecVideoAttr.bTemporalMvpEnable = 1;
            if (PT_H264 == pastSampleVdec[i].enType)
            {
                stChnAttr[i].stVdecVideoAttr.bTemporalMvpEnable = 0;
            }
            stChnAttr[i].u32FrameBufSize = VDEC_GetPicBufferSize(stChnAttr[i].enType, pastSampleVdec[i].u32Width, pastSampleVdec[i].u32Height,
                                                                 PIXEL_FORMAT_YVU_SEMIPLANAR_420, pastSampleVdec[i].stSapmleVdecVideo.enBitWidth, 0);

            CHECK_CHN_RET(HI_MPI_VDEC_CreateChn(i, &stChnAttr[i]), i, "HI_MPI_VDEC_CreateChn");
            CHECK_CHN_RET(HI_MPI_VDEC_GetChnParam(i, &stChnParam), i, "HI_MPI_VDEC_GetChnParam");
            stChnParam.stVdecVideoParam.enDecMode = pastSampleVdec[i].stSapmleVdecVideo.enDecMode;
            stChnParam.stVdecVideoParam.enCompressMode = COMPRESS_MODE_NONE;
            stChnParam.stVdecVideoParam.enVideoFormat = VIDEO_FORMAT_TILE_64x16;
            if (VIDEO_DEC_MODE_IPB == stChnParam.stVdecVideoParam.enDecMode)
            {
                stChnParam.stVdecVideoParam.enOutputOrder = VIDEO_OUTPUT_ORDER_DISP;
            }
            else
            {
                stChnParam.stVdecVideoParam.enOutputOrder = VIDEO_OUTPUT_ORDER_DEC;
            }
            stChnParam.u32DisplayFrameNum = pastSampleVdec[i].u32DisplayFrameNum;
            CHECK_CHN_RET(HI_MPI_VDEC_SetChnParam(i, &stChnParam), i, "HI_MPI_VDEC_GetChnParam");

            CHECK_CHN_RET(HI_MPI_VDEC_StartRecvStream(i), i, "HI_MPI_VDEC_StartRecvStream");
        }

        return HI_SUCCESS;
    }

//============================================================================================
// VDEC_Stop
//============================================================================================
HI_S32 SAMPLE_COMM_VDEC_Stop(HI_S32 s32ChnNum)
    {
        HI_S32 i;

        for (i = 0; i < s32ChnNum; i++)
        {
            CHECK_CHN_RET(HI_MPI_VDEC_StopRecvStream(i), i, "HI_MPI_VDEC_StopRecvStream");
            CHECK_CHN_RET(HI_MPI_VDEC_DestroyChn(i), i, "HI_MPI_VDEC_DestroyChn");
        }

        return HI_SUCCESS;
    }

//============================================================================================
// VDEC_SendStream
//============================================================================================

    int totalFrame = 1;
    int playFrame = 0;
    int decodeFrame = 0;
    int playFlag = 0;
    int decodeFlag = 0;
HI_VOID *SAMPLE_COMM_VDEC_SendStream(HI_VOID *pArgs)
    {
        VDEC_THREAD_PARAM_S *pstVdecThreadParam = (VDEC_THREAD_PARAM_S *)pArgs;
        HI_BOOL bEndOfStream = HI_FALSE;
        HI_S32 s32UsedBytes = 0, s32ReadLen = 0;
        FILE *fpStrm = NULL;
        HI_U8 *pu8Buf = NULL;
        VDEC_STREAM_S stStream;
        HI_BOOL bFindStart, bFindEnd;
        HI_U64 u64PTS = 0;
        HI_U32 u32Start;
        HI_S32 s32Ret, i;
        HI_CHAR cStreamFile[256];

        prctl(PR_SET_NAME, "VideoSendStream", 0, 0, 0);
        playFrame = 0;
        playFlag = 1;
        snprintf(cStreamFile, sizeof(cStreamFile), "%s/%s", pstVdecThreadParam->cFilePath, pstVdecThreadParam->cFileName);
        if (cStreamFile != 0)
        {
            fpStrm = fopen(cStreamFile, "rb");
            if (fpStrm == NULL)
            {
                SAMPLE_PRT("chn %d can't open file %s in send stream thread!\n", pstVdecThreadParam->s32ChnId, cStreamFile);
                return (HI_VOID *)(HI_FAILURE);
            }
        }
        printf("\n \033[0;36m chn %d, stream file:%s, userbufsize: %d \033[0;39m\n", pstVdecThreadParam->s32ChnId,
               pstVdecThreadParam->cFileName, pstVdecThreadParam->s32MinBufSize);

        pu8Buf = malloc(pstVdecThreadParam->s32MinBufSize);
        if (pu8Buf == NULL)
        {
            SAMPLE_PRT("chn %d can't alloc %d in send stream thread!\n", pstVdecThreadParam->s32ChnId, pstVdecThreadParam->s32MinBufSize);
            fclose(fpStrm);
            return (HI_VOID *)(HI_FAILURE);
        }
        fflush(stdout);

        u64PTS = pstVdecThreadParam->u64PtsInit;
        while (1)
        {
            if (pstVdecThreadParam->eThreadCtrl == THREAD_CTRL_STOP)
            {
                break;
            }
            else if (pstVdecThreadParam->eThreadCtrl == THREAD_CTRL_PAUSE)
            {
                sleep(1);
                continue;
            }

            bEndOfStream = HI_FALSE;
            bFindStart = HI_FALSE;
            bFindEnd = HI_FALSE;
            u32Start = 0;
            fseek(fpStrm, s32UsedBytes, SEEK_SET);
            s32ReadLen = fread(pu8Buf, 1, pstVdecThreadParam->s32MinBufSize, fpStrm);
            if (s32ReadLen == 0)
            {
                if (pstVdecThreadParam->bCircleSend == HI_TRUE)
                {
                    memset(&stStream, 0, sizeof(VDEC_STREAM_S));
                    stStream.bEndOfStream = HI_TRUE;
                    HI_MPI_VDEC_SendStream(pstVdecThreadParam->s32ChnId, &stStream, -1);

                    s32UsedBytes = 0;
                    fseek(fpStrm, 0, SEEK_SET);
                    s32ReadLen = fread(pu8Buf, 1, pstVdecThreadParam->s32MinBufSize, fpStrm);
                }
                else
                {
                    break;
                }
            }
            if (pstVdecThreadParam->s32StreamMode == VIDEO_MODE_FRAME && pstVdecThreadParam->enType == PT_H265)
            {
                HI_BOOL bNewPic = HI_FALSE;
                for (i = 0; i < s32ReadLen - 6; i++)
                {
                    HI_U32 tmp = (pu8Buf[i + 3] & 0x7E) >> 1;
                    bNewPic = (pu8Buf[i + 0] == 0 && pu8Buf[i + 1] == 0 && pu8Buf[i + 2] == 1 && (tmp >= 0 && tmp <= 21) && ((pu8Buf[i + 5] & 0x80) == 0x80));
                    if (bNewPic)
                    {
                        bFindStart = HI_TRUE;
                        i += 6;
                        break;
                    }
                }

                for (; i < s32ReadLen - 6; i++)
                {
                    HI_U32 tmp = (pu8Buf[i + 3] & 0x7E) >> 1;
                    bNewPic = (pu8Buf[i + 0] == 0 && pu8Buf[i + 1] == 0 && pu8Buf[i + 2] == 1 && (tmp == 32 || tmp == 33 || tmp == 34 || tmp == 39 || tmp == 40 || ((tmp >= 0 && tmp <= 21) && (pu8Buf[i + 5] & 0x80) == 0x80)));
                    if (bNewPic)
                    {
                        bFindEnd = HI_TRUE;
                        break;
                    }
                }
                if (i > 0)
                    s32ReadLen = i;

                if (bFindStart == HI_FALSE)
                {
                    SAMPLE_PRT("chn %d can not find H265 start code!s32ReadLen %d, s32UsedBytes %d.!\n",
                               pstVdecThreadParam->s32ChnId, s32ReadLen, s32UsedBytes);
                }
                if (bFindEnd == HI_FALSE)
                {
                    s32ReadLen = i + 6;
                }
            }
            stStream.u64PTS = u64PTS;
            stStream.pu8Addr = pu8Buf + u32Start;
            stStream.u32Len = s32ReadLen;
            stStream.bEndOfFrame = (pstVdecThreadParam->s32StreamMode == VIDEO_MODE_FRAME) ? HI_TRUE : HI_FALSE;
            stStream.bEndOfStream = bEndOfStream;
            stStream.bDisplay = 1;

        SendAgain:
            s32Ret = HI_MPI_VDEC_SendStream(pstVdecThreadParam->s32ChnId, &stStream, pstVdecThreadParam->s32MilliSec);
            if ((HI_SUCCESS != s32Ret) && (THREAD_CTRL_START == pstVdecThreadParam->eThreadCtrl))
            {
                usleep(pstVdecThreadParam->s32IntervalTime);
                goto SendAgain;
            }
            else
            {
                bEndOfStream = HI_FALSE;
                s32UsedBytes = s32UsedBytes + s32ReadLen + u32Start;
                u64PTS += pstVdecThreadParam->u64PtsIncrease;
                playFrame++;
            }
            usleep(pstVdecThreadParam->s32IntervalTime);
        }
        playFrame = totalFrame;
        /* send the flag of stream end */
        memset(&stStream, 0, sizeof(VDEC_STREAM_S));
        stStream.bEndOfStream = HI_TRUE;
        HI_MPI_VDEC_SendStream(pstVdecThreadParam->s32ChnId, &stStream, -1);

        printf("\033[0;35m chn %d send steam thread return ...  \033[0;39m\n", pstVdecThreadParam->s32ChnId);
        fflush(stdout);
        if (pu8Buf != HI_NULL)
        {
            free(pu8Buf);
        }
        fclose(fpStrm);
        pstVdecThreadParam->eThreadCtrl = THREAD_CTRL_STOP;
        return (HI_VOID *)HI_SUCCESS;
    }

//============================================================================================
// VDEC_StartSendStream
//============================================================================================
HI_VOID SAMPLE_COMM_VDEC_StartSendStream(HI_S32 s32ChnNum, VDEC_THREAD_PARAM_S *pstVdecSend, pthread_t *pVdecThread)
    {
        HI_S32 i;

        for (i = 0; i < s32ChnNum; i++)
        {
            pVdecThread[i] = 0;
            pthread_create(&pVdecThread[i], 0, SAMPLE_COMM_VDEC_SendStream, (HI_VOID *)&pstVdecSend[i]);
        }
    }

//============================================================================================
// VDEC_CmdCtrl
//============================================================================================
HI_VOID SAMPLE_COMM_VDEC_CmdCtrl(HI_S32 s32ChnNum, VDEC_THREAD_PARAM_S *pstVdecSend, pthread_t *pVdecThread)
    {
        HI_S32 i, s32Ret;
        VDEC_CHN_STATUS_S stStatus;
        printf("decoding..............");
        for (i = 0; i < s32ChnNum; i++)
        {
#if 0
            if(0 != pVdecThread[i])
            {
                s32Ret = pthread_join(pVdecThread[i], HI_NULL);
                if(0 == s32Ret)
                {
                    pVdecThread[i] = 0;
                }
            }
#endif
            printf("join\n");
            pVdecThread[i] = 0;
            while (1)
            {
                printf("start query\n");
                s32Ret = HI_MPI_VDEC_QueryStatus(pstVdecSend[i].s32ChnId, &stStatus);
                if (s32Ret != HI_SUCCESS)
                {
                    printf("chn %d HI_MPI_VDEC_QueryStatus fail!!!\n", s32Ret);
                    return;
                }
                // if((0 == stStatus.u32LeftStreamBytes)&&(0 == stStatus.u32LeftPics))
                {
                    PRINTF_VDEC_CHN_STATUS(pstVdecSend[i].s32ChnId, stStatus);
                    // break;
                }
                usleep(1000);
            }
        }
        printf("end!\n");
        return;
    }

//============================================================================================
// VDEC_StopSendStream
//============================================================================================
HI_VOID SAMPLE_COMM_VDEC_StopSendStream(HI_S32 s32ChnNum, VDEC_THREAD_PARAM_S *pstVdecSend, pthread_t *pVdecThread)
    {
        HI_S32 i;

        for (i = 0; i < s32ChnNum; i++)
        {
            pstVdecSend[i].eThreadCtrl = THREAD_CTRL_STOP;
            HI_MPI_VDEC_StopRecvStream(i);
            if (0 != pVdecThread[i])
            {
                pthread_join(pVdecThread[i], HI_NULL);
                pVdecThread[i] = 0;
            }
        }
    }

//=======================================================================================================
// OSD显示的图片路径，HDMI用的图片是有_ov426后缀的，  因为 3.5寸屏有旋转，而HDmi无旋转，所以图片的方向不一样
// OSD显示的图片路径，HDMI用的图片是有_ov426后缀的

/*
//MIPI-output
HI_CHAR *PATH_BAT[7]   ={"./res/batr.bmp","./res/baty.bmp","./res/batb1.bmp","./res/batb2.bmp",
                         "./res/batb3.bmp","./res/batb4.bmp","./res/batb5.bmp"};
HI_CHAR *PATH_SD[2]    ={"./res/sdr.bmp","./res/sdb.bmp"};
HI_CHAR *PATH_PHOTO    = "./res/photo.bmp";
HI_CHAR *PATH_PHOTO    = "./res/photo_b50.bmp";
HI_CHAR *PATH_PHOTO_H  = "./res/photo_f_n.bmp";
HI_CHAR *PATH_FREEZE   = "./res/freeze_b50.bmp";
HI_CHAR *PATH_RECORD   = "./res/record_r50.bmp";
HI_CHAR *PATH_LED      = "./res/light_b50.bmp";
HI_CHAR *PATH_TIME[12] ={"./res/time0.bmp","./res/time1.bmp","./res/time2.bmp","./res/time3.bmp","./res/time4.bmp",
                         "./res/time5.bmp","./res/time6.bmp","./res/time7.bmp","./res/time8.bmp","./res/time9.bmp",
                         "./res/timed.bmp","./res/timeu.bmp"};
HI_CHAR *PATH_BAT_OV426[7]   ={"./res/batr_ov426.bmp","./res/baty_ov426.bmp","./res/batb1_ov426.bmp","./res/batb2_ov426.bmp",
                               "./res/batb3_ov426.bmp","./res/batb4_ov426.bmp","./res/batb5_ov426.bmp"};
HI_CHAR *PATH_SD_OV426[2]    ={"./res/sdr_ov426.bmp","./res/sdb_ov426.bmp"};
HI_CHAR *PATH_PHOTO_OV426    = "./res/photo_ov426.bmp";
HI_CHAR *PATH_TIME_OV426[12] ={"./res/time0_ov426.bmp","./res/time1_ov426.bmp","./res/time2_ov426.bmp","./res/time3_ov426.bmp",
                               "./res/time4_ov426.bmp","./res/time5_ov426.bmp","./res/time6_ov426.bmp","./res/time7_ov426.bmp",
                               "./res/time8_ov426.bmp","./res/time9_ov426.bmp","./res/timed_ov426.bmp","./res/timeu_ov426.bmp"};
*/
//------------------------------------------------------------------------------------------------------------------------------
// Edwin add 10inch pad

    HI_CHAR *PATH_FREEZE_10INCH = "./res/10inch/freeze_b50.bmp";
    HI_CHAR *PATH_PHOTOS_10INCH = "./res/10inch/photo_b50.bmp";
    HI_CHAR *PATH_RECORD_10INCH = "./res/10inch/record_b50.bmp";
    HI_CHAR *PATH_LIGHTS_10INCH = "./res/10inch/led_b50.bmp";
    HI_CHAR *PATH_SDCARD_10INCH[2] = {"./res/10inch/sd0_w50.bmp", "./res/10inch/sd1_b50.bmp"};
    HI_CHAR *PATH_POWERS_10INCH[7] = {"./res/10inch/bat_01_50.bmp", "./res/10inch/bat_10_50.bmp",
                                      "./res/10inch/bat_20_50.bmp", "./res/10inch/bat_40_50.bmp",
                                      "./res/10inch/bat_60_50.bmp", "./res/10inch/bat_80_50.bmp",
                                      "./res/10inch/bat_100_50.bmp"};
    HI_CHAR *PATH_TIME_10INCH[12] = {"./res/time0_ov426.bmp", "./res/time1_ov426.bmp", "./res/time2_ov426.bmp",
                                     "./res/time3_ov426.bmp", "./res/time4_ov426.bmp", "./res/time5_ov426.bmp",
                                     "./res/time6_ov426.bmp", "./res/time7_ov426.bmp", "./res/time8_ov426.bmp",
                                     "./res/time9_ov426.bmp", "./res/timed_ov426.bmp", "./res/timeu_ov426.bmp"};
//------------------------------------------------------------------------------------------------------------------------------
    unsigned char image_bat[7][8192];
    unsigned char image_sd[2][8192];
    unsigned char image_photo[8192];
    unsigned char image_time[12][8192];
    unsigned char image_freeze[8192];
    unsigned char image_record[8192];
    unsigned char image_led[8192];

RGN_HANDLE MinHadle[16] = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35};
OSD_COMP_INFO s_OSDCompInfo[OSD_COLOR_FMT_BUTT] =
    {
            {0, 4, 4, 4}, /*RGB444*/
            {4, 4, 4, 4}, /*ARGB4444*/
            {0, 5, 5, 5}, /*RGB555*/
            {0, 5, 6, 5}, /*RGB565*/
            {1, 5, 5, 5}, /*ARGB1555*/
            {0, 0, 0, 0}, /*RESERVED*/
            {0, 8, 8, 8}, /*RGB888*/
            {8, 8, 8, 8}  /*ARGB8888*/
    };

VGS_ADD_OSD_S astVgsAddOsd[16];

//=======================================================================================================
//获取bmp信息
//=======================================================================================================
HI_S32 GetBmpInfo(const char *filename, OSD_BITMAPFILEHEADER *pBmpFileHeader, OSD_BITMAPINFO *pBmpInfo)
    {
        FILE *pFile;

        HI_U16 bfType;

        if (NULL == filename)
        {
            printf("OSD_LoadBMP: filename=NULL\n");
            return -1;
        }

        if ((pFile = fopen((char *)filename, "rb")) == NULL)
        {
            printf("Open file faild:%s!\n", filename);
            return -1;
        }

        (void)fread(&bfType, 1, sizeof(bfType), pFile);
        if (bfType != 0x4d42)
        {
            printf("not bitmap file\n");
            fclose(pFile);
            return -1;
        }

        (void)fread(pBmpFileHeader, 1, sizeof(OSD_BITMAPFILEHEADER), pFile);
        (void)fread(pBmpInfo, 1, sizeof(OSD_BITMAPINFO), pFile);
        fclose(pFile);

        return 0;
    }

//=======================================================================================================
char *GetExtName(char *filename)
    {
        char *pret = NULL;
        HI_U32 fnLen;

        if (NULL == filename)
        {
            printf("filename can't be null!");
            return NULL;
        }

        fnLen = strlen(filename);
        while (fnLen)
        {
            pret = filename + fnLen;
            if (*pret == '.')
            {
                return (pret + 1);
            }

            fnLen--;
        }

        return pret;
    }

//=======================================================================================================
//没有使用
//=======================================================================================================
HI_U16 OSD_MAKECOLOR_U16(HI_U8 r, HI_U8 g, HI_U8 b, OSD_COMP_INFO compinfo)
    {
        HI_U8 r1, g1, b1;
        HI_U16 pixel = 0;
        HI_U32 tmp = 15;

        r1 = g1 = b1 = 0;
        r1 = r >> (8 - compinfo.rlen);
        g1 = g >> (8 - compinfo.glen);
        b1 = b >> (8 - compinfo.blen);
        while (compinfo.alen)
        {
            pixel |= (1 << tmp);
            tmp--;
            compinfo.alen--;
        }

        pixel |= (r1 | (g1 << compinfo.blen) | (b1 << (compinfo.blen + compinfo.glen)));
        return pixel;
    }

//=======================================================================================================
// 海思自带， 没有使用
//=======================================================================================================
int LoadBMPCanvas(const char *filename, OSD_LOGO_T *pVideoLogo, OSD_COLOR_FMT_E enFmt)
{
        FILE *pFile;
        HI_U16 i, j;

        HI_U32 w, h;
        HI_U16 Bpp;

        OSD_BITMAPFILEHEADER bmpFileHeader;
        OSD_BITMAPINFO bmpInfo;

        HI_U8 *pOrigBMPBuf;
        HI_U8 *pRGBBuf;
        HI_U32 stride;
        HI_U8 r, g, b;
        HI_U8 *pStart;
        HI_U16 *pDst;

        if (NULL == filename)
        {
            printf("OSD_LoadBMP: filename=NULL\n");
            return -1;
        }

        if (GetBmpInfo(filename, &bmpFileHeader, &bmpInfo) < 0)
        {
            return -1;
        }

        Bpp = bmpInfo.bmiHeader.biBitCount / 8;
        if (Bpp < 2)
        {
            /* only support 1555.8888  888 bitmap */
            printf("bitmap format not supported!\n");
            return -1;
        }

        if (bmpInfo.bmiHeader.biCompression != 0)
        {
            printf("not support compressed bitmap file!\n");
            return -1;
        }

        if (bmpInfo.bmiHeader.biHeight < 0)
        {
            printf("bmpInfo.bmiHeader.biHeight < 0\n");
            return -1;
        }

        if ((pFile = fopen((char *)filename, "rb")) == NULL)
        {
            printf("Open file faild:%s!\n", filename);
            return -1;
        }

        w = (HI_U16)bmpInfo.bmiHeader.biWidth;
        h = (HI_U16)((bmpInfo.bmiHeader.biHeight > 0) ? bmpInfo.bmiHeader.biHeight : (-bmpInfo.bmiHeader.biHeight));

        stride = w * Bpp;

#if 1
        if (stride % 4)
        {
            stride = (stride & 0xfffc) + 4;
        }
#endif

        /* RGB8888 or RGB1555 */
        pOrigBMPBuf = (HI_U8 *)malloc(h * stride);
        if (NULL == pOrigBMPBuf)
        {
            printf("not enough memory to malloc!\n");
            fclose(pFile);
            return -1;
        }

        pRGBBuf = pVideoLogo->pRGBBuffer;

        if (stride > pVideoLogo->stride)
        {
            printf("Bitmap's stride(%d) is bigger than canvas's stide(%d). Load bitmap error!\n", stride, pVideoLogo->stride);
            free(pOrigBMPBuf);
            fclose(pFile);
            return -1;
        }

        if (h > pVideoLogo->height)
        {
            printf("Bitmap's height(%d) is bigger than canvas's height(%d). Load bitmap error!\n", h, pVideoLogo->height);
            free(pOrigBMPBuf);
            fclose(pFile);
            return -1;
        }

        if (w > pVideoLogo->width)
        {
            printf("Bitmap's width(%d) is bigger than canvas's width(%d). Load bitmap error!\n", w, pVideoLogo->width);
            free(pOrigBMPBuf);
            fclose(pFile);
            return -1;
        }

        fseek(pFile, bmpFileHeader.bfOffBits, 0);
        if (fread(pOrigBMPBuf, 1, h * stride, pFile) != (h * stride))
        {
            printf("fread (%d*%d)error!line:%d\n", h, stride, __LINE__);
            perror("fread:");
        }

        for (i = 0; i < h; i++)
        {
            for (j = 0; j < w; j++)
            {
                if (Bpp == 3) /*.....*/
                {
                    switch (enFmt)
                    {
                    case OSD_COLOR_FMT_RGB444:
                    case OSD_COLOR_FMT_RGB555:
                    case OSD_COLOR_FMT_RGB565:
                    case OSD_COLOR_FMT_RGB1555:
                    case OSD_COLOR_FMT_RGB4444:
                        /* start color convert */
                        pStart = pOrigBMPBuf + ((h - 1) - i) * stride + j * Bpp;
                        pDst = (HI_U16 *)(pRGBBuf + i * pVideoLogo->stride + j * 2);
                        r = *(pStart);
                        g = *(pStart + 1);
                        b = *(pStart + 2);
                        // printf("Func: %s, line:%d, Bpp: %d, bmp stride: %d, Canvas stride: %d, h:%d, w:%d.\n",
                        //     __FUNCTION__, __LINE__, Bpp, stride, pVideoLogo->stride, i, j);
                        *pDst = OSD_MAKECOLOR_U16(r, g, b, s_OSDCompInfo[enFmt]);

                        break;

                    case OSD_COLOR_FMT_RGB888:
                    case OSD_COLOR_FMT_RGB8888:
                        memcpy(pRGBBuf + i * pVideoLogo->stride + j * 4, pOrigBMPBuf + ((h - 1) - i) * stride + j * Bpp, Bpp);
                        *(pRGBBuf + i * pVideoLogo->stride + j * 4 + 3) = 0xff; /*alpha*/
                        break;

                    default:
                        printf("file(%s), line(%d), no such format!\n", __FILE__, __LINE__);
                        break;
                    }
                }
                else if ((Bpp == 2) || (Bpp == 4)) /*..............*/
                {
                    memcpy(pRGBBuf + i * pVideoLogo->stride + j * Bpp, pOrigBMPBuf + ((h - 1) - i) * stride + j * Bpp, Bpp);
                }
            }
        }

        free(pOrigBMPBuf);
        pOrigBMPBuf = NULL;

        fclose(pFile);
        return 0;
    }

//=======================================================================================================
//海思自带OSD读取图片,  没有使用
//=======================================================================================================
int LoadCanvasEx(const char *filename, OSD_LOGO_T *pVideoLogo, OSD_COLOR_FMT_E enFmt)
    {
        char *ext = GetExtName((char *)filename);

        if (HI_NULL == ext)
        {
            printf("LoadCanvasEx error!\n");
            return -1;
        }

        if (strcmp(ext, "bmp") == 0)
        {
            if (0 != LoadBMPCanvas(filename, pVideoLogo, enFmt))
            {
                printf("OSD_LoadBMP error!\n");
                return -1;
            }
        }
        else
        {
            printf("not supported image file!\n");
            return -1;
        }

        return 0;
    }

//=======================================================================================================
// 海思自带osd创建画布,
//=======================================================================================================
HI_S32 CreateSurfaceByCanvas(const HI_CHAR *pszFileName, OSD_SURFACE_S *pstSurface, HI_U8 *pu8Virt, HI_U32 u32Width, HI_U32 u32Height, HI_U32 u32Stride)
    {
        OSD_LOGO_T stLogo;
        stLogo.pRGBBuffer = pu8Virt;
        stLogo.width = u32Width;
        stLogo.height = u32Height;
        stLogo.stride = u32Stride;
        if (LoadCanvasEx(pszFileName, &stLogo, pstSurface->enColorFmt) < 0)
        {
            printf("load bmp error!\n");
            return -1;
        }

        pstSurface->u16Height = u32Height;
        pstSurface->u16Width = u32Width;
        pstSurface->u16Stride = u32Stride;

        return 0;
    }

//=======================================================================================================
//海思自己画OSD
//=======================================================================================================
HI_S32 REGION_MST_UpdateCanvas(const char *filename, BITMAP_S *pstBitmap, HI_BOOL bFil,
                                   HI_U32 u16FilColor, SIZE_S *pstSize, HI_U32 u32Stride, PIXEL_FORMAT_E enPixelFmt)
    {
        OSD_SURFACE_S Surface;
        OSD_BITMAPFILEHEADER bmpFileHeader;
        OSD_BITMAPINFO bmpInfo;

        if (GetBmpInfo(filename, &bmpFileHeader, &bmpInfo) < 0)
        {
            printf("GetBmpInfo err!\n");
            return HI_FAILURE;
        }

        if (PIXEL_FORMAT_ARGB_1555 == enPixelFmt)
        {
            Surface.enColorFmt = OSD_COLOR_FMT_RGB1555;
        }
        else if (PIXEL_FORMAT_ARGB_4444 == enPixelFmt)
        {
            Surface.enColorFmt = OSD_COLOR_FMT_RGB4444;
        }
        else if (PIXEL_FORMAT_ARGB_8888 == enPixelFmt)
        {
            Surface.enColorFmt = OSD_COLOR_FMT_RGB8888;
        }
        else
        {
            printf("Pixel format is not support!\n");
            return HI_FAILURE;
        }

        if (NULL == pstBitmap->pData)
        {
            printf("malloc osd memroy err!\n");
            return HI_FAILURE;
        }

        CreateSurfaceByCanvas(filename, &Surface, (HI_U8 *)(pstBitmap->pData), pstSize->u32Width, pstSize->u32Height, u32Stride);

        pstBitmap->u32Width = Surface.u16Width;
        pstBitmap->u32Height = Surface.u16Height;

        if (PIXEL_FORMAT_ARGB_1555 == enPixelFmt)
        {
            pstBitmap->enPixelFormat = PIXEL_FORMAT_ARGB_1555;
        }
        else if (PIXEL_FORMAT_ARGB_4444 == enPixelFmt)
        {
            pstBitmap->enPixelFormat = PIXEL_FORMAT_ARGB_4444;
        }
        else if (PIXEL_FORMAT_ARGB_8888 == enPixelFmt)
        {
            pstBitmap->enPixelFormat = PIXEL_FORMAT_ARGB_8888;
        }

        int i, j;
        HI_U16 *pu16Temp;
        pu16Temp = (HI_U16 *)pstBitmap->pData;

        if (bFil)
        {
            for (i = 0; i < pstBitmap->u32Height; i++)
            {
                for (j = 0; j < pstBitmap->u32Width; j++)
                {
                    if (u16FilColor == *pu16Temp)
                    {
                        *pu16Temp &= 0x7FFF;
                    }

                    pu16Temp++;
                }
            }
        }

        return HI_SUCCESS;
    }

//=======================================================================================================
// 没有使用
//=======================================================================================================
int mppOsdCreate(int x, int y, int width, int height, RGN_HANDLE handle1, RGN_HANDLE handle2, HI_CHAR *PIC)
    {
        return HI_SUCCESS;
    }

//=======================================================================================================
//没有使用 海思自己--OsdDelete
//=======================================================================================================
int mppOsdDelete(RGN_HANDLE handle)
    {

        return HI_SUCCESS;
    }

//=======================================================================================================
// 没有使用
//=======================================================================================================
int mppOsdUpdate(RGN_HANDLE handle, HI_CHAR *PIC)
    {
        return HI_SUCCESS;
    }

//=======================================================================================================
// Caputure 内使用
//=======================================================================================================
HI_S32 mppOsdCreate2(int x, int y, int width, int height, RGN_HANDLE handle, HI_CHAR *PIC, VGS_ADD_OSD_S *pstVgsAddOsd)
    {
        HI_S32 s32Ret;
        RGN_ATTR_S stRgnAttr;
        RGN_CANVAS_INFO_S stRgnCanvasInfo;
        BITMAP_S Bitmap;
        SIZE_S stOsd;
        stRgnAttr.enType = OVERLAYEX_RGN;
        stRgnAttr.unAttr.stOverlay.enPixelFmt = PIXEL_FORMAT_ARGB_1555;
        stRgnAttr.unAttr.stOverlayEx.stSize.u32Height = height; // 100;
        stRgnAttr.unAttr.stOverlayEx.stSize.u32Width = width;   // 100;
        stRgnAttr.unAttr.stOverlayEx.u32BgColor = 0x00000000;
        stRgnAttr.unAttr.stOverlayEx.u32CanvasNum = 2;
        s32Ret = HI_MPI_RGN_Create(handle, &stRgnAttr);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_RGN_create failed with %#x!\n", s32Ret);
            return HI_FAILURE;
        }
        s32Ret = HI_MPI_RGN_GetCanvasInfo(handle, &stRgnCanvasInfo);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_RGN_get can vasinfo failed with %#x!\n", s32Ret);
            return HI_FAILURE;
        }
        Bitmap.pData = (HI_VOID *)(HI_UL)stRgnCanvasInfo.u64VirtAddr;
        stOsd.u32Width = stRgnCanvasInfo.stSize.u32Width;
        stOsd.u32Height = stRgnCanvasInfo.stSize.u32Height;
        //    REGION_MST_UpdateCanvas(PIC, &Bitmap, HI_FALSE, 0, &stOsd, stRgnCanvasInfo.u32Stride, PIXEL_FORMAT_ARGB_1555);
        s32Ret = HI_MPI_RGN_UpdateCanvas(handle);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_RGN_Updat failed with %#x!\n", s32Ret);
            return HI_FAILURE;
        }
        pstVgsAddOsd->stRect.s32X = x;
        pstVgsAddOsd->stRect.s32Y = y;
        pstVgsAddOsd->stRect.u32Width = width;
        pstVgsAddOsd->stRect.u32Height = height;
        pstVgsAddOsd->u32BgColor = 0x00000000;
        pstVgsAddOsd->enPixelFmt = PIXEL_FORMAT_ARGB_1555;
        pstVgsAddOsd->u64PhyAddr = stRgnCanvasInfo.u64PhyAddr;
        pstVgsAddOsd->u32Stride = stRgnCanvasInfo.u32Stride;
        pstVgsAddOsd->u32BgAlpha = 255;
        pstVgsAddOsd->u32FgAlpha = 255;
        pstVgsAddOsd->bOsdRevert = HI_FALSE;
        pstVgsAddOsd->stOsdRevert.stSrcRect = pstVgsAddOsd->stRect;
        pstVgsAddOsd->stOsdRevert.enColorRevertMode = VGS_COLOR_REVERT_BOTH;
        return HI_SUCCESS;
    }

//=======================================================================================================
// USE
//=======================================================================================================
int mppOsdUpdateOne(int x, int y, int width, int height, RGN_HANDLE handle, HI_CHAR *PIC, VGS_ADD_OSD_S *pstVgsAddOsd)
    {
        BITMAP_S stBitmap;
        SIZE_S stSizeOsd;
        RGN_CANVAS_INFO_S stCanvasInfo;
        HI_MPI_RGN_GetCanvasInfo(handle, &stCanvasInfo);
        stBitmap.pData = (HI_VOID *)(HI_UL)stCanvasInfo.u64VirtAddr;
        stSizeOsd.u32Width = stCanvasInfo.stSize.u32Width;
        stSizeOsd.u32Height = stCanvasInfo.stSize.u32Height;
        //    REGION_MST_UpdateCanvas(PIC, &stBitmap, HI_FALSE, 0, &stSizeOsd, stCanvasInfo.u32Stride, PIXEL_FORMAT_ARGB_1555);
        HI_MPI_RGN_UpdateCanvas(handle);
        pstVgsAddOsd->stRect.s32X = x;
        pstVgsAddOsd->stRect.s32Y = y;
        pstVgsAddOsd->stRect.u32Width = width;
        pstVgsAddOsd->stRect.u32Height = height;
        pstVgsAddOsd->u32BgColor = 0x00000000;
        pstVgsAddOsd->enPixelFmt = PIXEL_FORMAT_ARGB_1555;
        pstVgsAddOsd->u64PhyAddr = stCanvasInfo.u64PhyAddr;
        pstVgsAddOsd->u32Stride = stCanvasInfo.u32Stride;
        pstVgsAddOsd->u32BgAlpha = 255;
        pstVgsAddOsd->u32FgAlpha = 255;
        pstVgsAddOsd->bOsdRevert = HI_FALSE;
        pstVgsAddOsd->stOsdRevert.stSrcRect = pstVgsAddOsd->stRect;
        pstVgsAddOsd->stOsdRevert.enColorRevertMode = VGS_COLOR_REVERT_BOTH;
        return HI_SUCCESS;
    }

//=======================================================================================================
// INIT一个osd 水印图片
//=======================================================================================================
static void picInitOne(HI_CHAR *file, int width, int heigh, unsigned char *pbuf, int revert)
    {
        int fd, i;
        unsigned char buf[200];
        fd = open(file, O_RDWR);
        read(fd, pbuf, 0x36);
        if ((width * 3) % 4)
        {
            for (i = 0; i < heigh; i++)
            {
                read(fd, &pbuf[i * width * 3], width * 3);
                read(fd, buf, 4 - (width & 3));
            }
        }
        else
        {
            read(fd, pbuf, width * heigh * 3);
        }
        close(fd);
    }

//=======================================================================================================
//初始化OSD图片,将7个类型的图片初始化
//=======================================================================================================
static void picInit()
    {
        int i;
        for (i = 0; i < 7; i++)
            picInitOne(PATH_POWERS_10INCH[i], BATTERY_WIDTH, BATTERY_HEIGHT, image_bat[i], 0); //电量图片7张
        for (i = 0; i < 2; i++)
            picInitOne(PATH_SDCARD_10INCH[i], SD_WIDTH, SD_HEIGHT, image_sd[i], 0); // SD卡图片2个
        for (i = 0; i < 12; i++)
            picInitOne(PATH_TIME_10INCH[i], TIME_WIDTH, TIME_HEIGHT, image_time[i], 0); //日期图片12个

        picInitOne(PATH_LIGHTS_10INCH, LED_WIDTH, LED_HEIGHT, image_led, 0);          // led图片
        picInitOne(PATH_PHOTOS_10INCH, PHOTO_WIDTH, PHOTO_HEIGHT, image_photo, 0);    //拍照提示图标
        picInitOne(PATH_RECORD_10INCH, RECORD_WIDTH, RECORD_HEIGHT, image_record, 0); //录像提示图标
        picInitOne(PATH_FREEZE_10INCH, FREEZE_WIDTH, FREEZE_HEIGHT, image_freeze, 0); //冻结提示图标
    }

//=======================================================================================================
// fbp初始化，主要是清0以后把RGBA里的A通道设为255
//=======================================================================================================
void mppOsdInit()
{
    memset(osdBuf, 0, SCREEN_WIDTH * SCREEN_HEIGHT * 4); // 10寸屏的buffer
    memset(osdBufHdmi, 0, 1920 * 1080 * 4);              // HDMI的buffer ,此处并未更新osdBufHdmi?
}

//=======================================================================================================
//屏幕上单个OSD图片显示---MIPI状态
//=======================================================================================================
// x      -->图标放置的行起始点;
// y      -->图标放置的列起始点;
// width  -->图标的宽度，
// heigh  -->图标的高度;
//*image -->图标的缓存image地址指针
//*buf   -->屏幕尺寸大小的缓冲buf地址指针;
// revert -->状态

void picUpdateOne(int x, int y, int width, int heigh, unsigned char *image, unsigned char *buf, int revert)
    {
        // SCREEN_WIDTH-->10寸触摸屏的有效像素宽度
        int i, j;                           // j=图标的列,i=图标的行
        int k;                              // k-->图片的第几通道
        int index;                          //像素点的位置
        int offset;                         //水平方向偏移
        index = (x + y * SCREEN_WIDTH) * 4; // index ->第y行第x个像数，一个像素4字节32bits
        offset = 4 * (SCREEN_WIDTH - width);

        k = 0;
        for (i = 0; i < heigh; i++)
        {
            for (j = 0; j < width; j++)
            {
                if (revert == 0) // normal show　正常显示图片
                {
                    buf[index] = image[k];
                    buf[index + 1] = image[k + 1];
                    buf[index + 2] = image[k + 2];
                    buf[index + 3] = 253;
                }
                else if (revert == 1) // show time　显示时间logo
                {
                    if (image[k] != 255)
                    {
                        buf[index] = 255;
                        buf[index + 1] = 255;
                        buf[index + 2] = 255;
                        buf[index + 3] = 253;
                    }
                    else
                    {
                        if (buf[index + 3] == 255)
                        {
                            buf[index] = 0;
                            buf[index + 1] = 0;
                            buf[index + 2] = 0;
                            buf[index + 3] = 0;
                        }
                        if (buf[index + 3] == 253)
                        {
                            buf[index] = 0;
                            buf[index + 1] = 0;
                            buf[index + 2] = 0;
                            buf[index + 3] = 0;
                        }
                    }
                }
                else if (revert == 2) // stop　停止显示logo
                {
                    buf[index] = 0;
                    buf[index + 1] = 0;
                    buf[index + 2] = 0;
                    if (buf[index + 3] != 254)
                        buf[index + 3] = 0;
                    else
                        buf[index + 3] = 254;
                }
                else if (revert == 3) // show white background　显示白色背景的logo
                {
                    if (image[k] == 255)
                    {
                        buf[index] = 0;
                        buf[index + 1] = 0;
                        buf[index + 2] = 0;

                        if (buf[index + 3] != 254)
                            buf[index + 3] = 0;
                        else
                            buf[index + 3] = 254;
                    }
                    else
                    {
                        buf[index] = image[k];
                        buf[index + 1] = image[k + 1];
                        buf[index + 2] = image[k + 2];
                        buf[index + 3] = 253;
                    }
                }
                index += 4;
                k += 3;
            }
            index += offset;
        }
    }

//=======================================================================================================
//屏幕上单个OSD图片显示---HDMI状态
//=======================================================================================================
// x->图标放置的行起始点，
// y->图标放置的列起始点;
// width-->图标的宽度， heigh-->图标的高度;
//*image -->图标的缓存image地址指针
//*buf   -->屏幕尺寸大小的缓冲buf地址指针;
// revert -->状态
void picUpdateOneHdmi(int x, int y, int width, int heigh, unsigned char *image, unsigned char *buf, int revert)
    {
        int hdmi_W; // HDMI输出尺寸的宽度
        int i, j;                                                  // j=图标的列,i=图标的行
        int k;                                                     // k-->图片的第几通道
        int index;                                                 //像素点的位置
        int offset;                                                //水平方向偏移
        switch(hdmi_disp_mode)
        {
            case HDMI_1080P:     hdmi_W = 1920; break;
            case HDMI_1920x1200: hdmi_W = 1920; break;
        }
        index = (x + y * hdmi_W) * 4;                              // index ->第y行第x个像数，一个像素4字节32bits
        offset = 4 * (hdmi_W - width);
        k = 0;

        for (i = 0; i < heigh; i++)
        {
            for (j = 0; j < width; j++)
            {
                if (revert == 0) // normal show
                {
                    buf[index] = image[k];
                    buf[index + 1] = image[k + 1];
                    buf[index + 2] = image[k + 2];
                    buf[index + 3] = 253;
                }
                else if (revert == 1) //状态1，显示日期信息
                {
                    if (image[k] != 255)
                    {
                        buf[index] = 255;
                        buf[index + 1] = 255;
                        buf[index + 2] = 255;
                        buf[index + 3] = 253;
                    }
                    else
                    {
                        if (buf[index + 3] == 255)
                        {
                            buf[index] = 0;
                            buf[index + 1] = 0;
                            buf[index + 2] = 0;
                            buf[index + 3] = 0;
                        }
                        if (buf[index + 3] == 253)
                        {
                            buf[index] = 0;
                            buf[index + 1] = 0;
                            buf[index + 2] = 0;
                            buf[index + 3] = 0;
                        }
                    }
                }
                else if (revert == 2) //状态2，不显示图标
                {
                    buf[index] = 0;
                    buf[index + 1] = 0;
                    buf[index + 2] = 0;
                    if (buf[index + 3] != 254)
                        buf[index + 3] = 0;
                    else
                        buf[index + 3] = 254;
                }
                else if (revert == 3) //状态3，显示图标
                {
                    if (image[k] == 255)
                    {
                        buf[index] = 0;
                        buf[index + 1] = 0;
                        buf[index + 2] = 0;
                        if (buf[index + 3] != 254)
                            buf[index + 3] = 0;
                        else
                            buf[index + 3] = 254;
                    }
                    else
                    {
                        buf[index] = image[k];
                        buf[index + 1] = image[k + 1];
                        buf[index + 2] = image[k + 2];
                        buf[index + 3] = 253;
                    }
                }
                index += 4;
                k += 3;
            }
            index += offset;
        }
    }

//=======================================================================================================
//画面遮罩函数，分别有C角，圆角和圆形
//=======================================================================================================
    /*
            ----------------------------size_w---------------------------------
            |            |                                                     |
            |            |                                                     |
            |            y                                                     |
            |            |                                                     |
            |            |                                                     |
            |-----X---------------------size_l------------ -------             |
            |            |                                        |            |
            |            |                                        |            |
            |            |                                        |            |
            |         size_l                                      |            |
            |            |                                       /|            |
            |            |                                      / |            |
            |            |                                     /  |heigh       |
            |            |                                    /   |            |
            |            ------------------------------------/-----            |
            |                                                  width           |
            |                                                                  |
            |                                                                  |
            |                                                                  |
            |                                                                  |
            --------------------------------------------------------------------
    */
void RC_mask(unsigned char *buf, int mode)
    {
        int i, j, index, size_w, size_l, x, y = 240, heigh, width, radio, circular;
        // size_w   HDMI显示的画布宽度，也等于显示总宽度
        // size_l   裁切后保留的图片宽度
        //  X       图像的起始位置
        //  Y       图像的起始位置
        // radio    圆角的半径
        // circular 圆的半径
        switch(hdmi_disp_mode)
        {
            case HDMI_1080P:
                size_w = 1920;
                switch (hdmi_size)
                {
                case 1: // 400x400
                    x = 760;
                    y = 340;
                    size_l = 400;
                    break;
                case 2: // 600x600
                    x = 660;
                    y = 240;
                    size_l = 600;
                    break;
                case 3: // 800x800
                    x = 560;
                    y = 140;
                    size_l = 800;
                    break;
                case 4: // 1000x1000
                    x = 560;//460;
                    y = 40;
                    size_l = 1000;
                    break;
                default:
                    x = 660;
                    y = 240;
                    size_l = 600;
                    break;
                }
            break;
            case HDMI_1920x1200:
                size_w = 1920;
                switch (hdmi_size)
                {
                case 1: // 400x400
                    x = 760;
                    y = 340;
                    size_l = 400;
                    break;
                case 2: // 600x600
                    x = 660;
                    y = 240;
                    size_l = 600;
                    break;
                case 3: // 800x800
                    x = 560;
                    y = 140;
                    size_l = 800;
                    break;
                case 4: // 1000x1000
                    x = 560;
                    y = 40;
                    size_l = 1000;
                    break;
                default:
                    x = 660;
                    y = 240;
                    size_l = 600;
                    break;
                }
            break;
        }
        heigh = width = size_l / 8; // C角
        radio = size_l / 8;         //圆角的半径
        circular = size_l / 2;      //圆的半径
        //------------------------------------------------------------------------------------------------------------------------
        // for(i=0;i<size_l;i++)
        //     memset(buf+(x+(y+i)*size_w)*4,0,4*size_l);
        for (i = 0; i < size_l; i++) //有效图像的左上角的黑色C角
        {
            index = (x + (y + i) * size_w) * 4;
            for (j = 0; j < size_l; j++)
            {
                if (buf[index + 3] != 253)
                {
                    buf[index + 0] = 0;
                    buf[index + 1] = 0;
                    buf[index + 2] = 0;
                    buf[index + 3] = 0;
                } //遮罩层是A值254，OSD显示层是A值253，根据这个来实现OSD层显示在遮罩上方
                index += 4;
            }
        }

        switch (mode)
        {
        case 0: //切R角
            for (i = 0; i < radio; i++)
            {
                index = (x + (y + i) * size_w) * 4;
                for (j = 0; j < radio; j++)
                {
                    if ((radio - j) * (radio - j) + (radio - i) * (radio - i) < radio * radio)
                        break;
                    if (buf[index + 3] != 253)
                    {
                        buf[index] = 0;
                        buf[index + 1] = 0;
                        buf[index + 2] = 0;
                        buf[index + 3] = 254;
                    }
                    index += 4;
                }
            }
            for (i = 0; i < radio; i++)
            {
                index = (x + size_l - radio + (y + i) * size_w) * 4;
                for (j = 0; j < radio; j++)
                {
                    if (j * j + (radio - i) * (radio - i) > radio * radio)
                    {
                        if (buf[index + 3] != 253)
                        {
                            buf[index] = 0;
                            buf[index + 1] = 0;
                            buf[index + 2] = 0;
                            buf[index + 3] = 254;
                        }
                    }
                    index += 4;
                }
            }
            for (i = 0; i < radio; i++)
            {
                index = (x + (size_l - radio + y + i) * size_w) * 4;
                for (j = 0; j < i; j++)
                {
                    if ((radio - j) * (radio - j) + i * i < radio * radio)
                        break;
                    if (buf[index + 3] != 253)
                    {
                        buf[index] = 0;
                        buf[index + 1] = 0;
                        buf[index + 2] = 0;
                        buf[index + 3] = 254;
                    }
                    index += 4;
                }
            }
            for (i = 0; i < radio; i++)
            {
                index = (x + size_l - radio + (size_l - radio + y + i) * size_w) * 4;
                for (j = 0; j < radio; j++)
                {
                    if (j * j + i * i > radio * radio)
                    {
                        if (buf[index + 3] != 253)
                        {
                            buf[index] = 0;
                            buf[index + 1] = 0;
                            buf[index + 2] = 0;
                            buf[index + 3] = 254;
                        }
                    }
                    index += 4;
                }
            }
            break;
        case 1: //直角
            break;
        case 2:                         //三角
            for (i = 0; i < heigh; i++) //有效图像的左上角的黑色C角
            {
                index = (x + (y + i) * size_w) * 4;
                for (j = 0; j < width - i; j++)
                {
                    if (buf[index + 3] != 253)
                    {
                        buf[index + 0] = 0;
                        buf[index + 1] = 0;
                        buf[index + 2] = 0;
                        buf[index + 3] = 254;
                    } //遮罩层是A值254，OSD显示层是A值253，根据这个来实现OSD层显示在遮罩上方
                    index += 4;
                }
            }
            for (i = 0; i < heigh; i++) //有效图像的右上角的黑色C角
            {
                index = (x + size_l - width + i + (y + i) * size_w) * 4;
                for (j = 0; j < width - i; j++)
                {
                    if (buf[index + 3] != 253)
                    {
                        buf[index + 0] = 0;
                        buf[index + 1] = 0;
                        buf[index + 2] = 0;
                        buf[index + 3] = 254;
                    }
                    index += 4;
                }
            }
            for (i = 0; i < heigh; i++) //有效图像的左下角的黑色C角
            {
                index = (x + (size_l - heigh + i + y) * size_w) * 4;
                for (j = 0; j < i; j++)
                {
                    if (buf[index + 3] != 253)
                    {
                        buf[index + 0] = 0;
                        buf[index + 1] = 0;
                        buf[index + 2] = 0;
                        buf[index + 3] = 254;
                    }
                    index += 4;
                }
            }
            for (i = 0; i < heigh; i++) //有效图像的右下角的黑色C角
            {
                index = (x + size_l - i + (size_l - heigh + i + y) * size_w) * 4;
                for (j = 0; j < i; j++)
                {
                    if (buf[index + 3] != 253)
                    {
                        buf[index + 0] = 0;
                        buf[index + 1] = 0;
                        buf[index + 2] = 0;
                        buf[index + 3] = 254;
                    }
                    index += 4;
                }
            }
            break;
        case 3: //圆形
            for (i = 0; i < circular; i++)
            {
                index = (x + (y + i) * size_w) * 4;
                for (j = 0; j < circular; j++)
                {
                    if ((circular - j) * (circular - j) + (circular - i) * (circular - i) < circular * circular)
                        break;
                    if (buf[index + 3] != 253)
                    {
                        buf[index + 0] = 0;
                        buf[index + 1] = 0;
                        buf[index + 2] = 0;
                        buf[index + 3] = 254;
                    }
                    index += 4;
                }
            }
            for (i = 0; i < circular; i++)
            {
                index = (x + size_l - circular + (y + i) * size_w) * 4;
                for (j = 0; j < circular; j++)
                {
                    if (j * j + (circular - i) * (circular - i) > circular * circular)
                    {
                        if (buf[index + 3] != 253)
                        {
                            buf[index + 0] = 0;
                            buf[index + 1] = 0;
                            buf[index + 2] = 0;
                            buf[index + 3] = 254;
                        }
                    }
                    index += 4;
                }
            }
            for (i = 0; i < circular; i++)
            {
                index = (x + (size_l - circular + (y + i)) * size_w) * 4;
                for (j = 0; j < i; j++)
                {
                    if ((circular - j) * (circular - j) + i * i < circular * circular)
                        break;
                    if (buf[index + 3] != 253)
                    {
                        buf[index + 0] = 0;
                        buf[index + 1] = 0;
                        buf[index + 2] = 0;
                        buf[index + 3] = 254;
                    }
                    index += 4;
                }
            }
            for (i = 0; i < circular; i++)
            {
                index = (x + size_l - circular + (size_l - circular + (y + i)) * size_w) * 4;
                for (j = 0; j < circular; j++)
                {
                    if (j * j + i * i > circular * circular)
                    {
                        if (buf[index + 3] != 253)
                        {
                            buf[index + 0] = 0;
                            buf[index + 1] = 0;
                            buf[index + 2] = 0;
                            buf[index + 3] = 254;
                        }
                    }
                    index += 4;
                }
            }
            break;
        default:
            break;
        }
    }

//=======================================================================================================
// HDMI的buffer 和 mipi的buffer独立，都由此函数控制     OSD水印 更新
//=======================================================================================================
int mppOsdInfoUpdate() // OSD更新函数
    {
        static int init = 0;
        if (init == 0) //初始化osd上的水印图标
        {
            init = 1;
            picInit();    //初始化OSD图片,---20220704 edwin
            mppOsdInit(); // fbp初始化，主要是清0以后把RGBA里的A通道设为255
        }
    }

//=======================================================================================================
// 刷新 freambuffer    显示的freambuffer
//=======================================================================================================
// mode0: with toolbar mode1: full mode2: play  mode3:no video,mode4:hdmi
void mppClean(int mode, unsigned char *fbp, int immediate)
    {
        //用于设置fbp的值，输出图像的位置fbp要设置成0，显示UI的地方fbp不设置
        int i;
        static int cnt = 0;
        if (1)
        {
            switch (mode)
            {
                // void *memcpy（void *dest， const void *src， size_t n）;
                //从源"src"所指的内存地址的起始位置开始拷贝"n"个字节到目标"dest"所指的内存地址的起始位置中
                // "fbp" = 目标"dest",

            case 0: // With toolbar mode用工具栏

                for (i = 0; i < BLANK_OFFSET; i++) // copy top 2 rows to fpb
                {
                    memcpy(fbp + i * SCREEN_WIDTH * 4, osdBuf + i * SCREEN_WIDTH * 4, SCREEN_WIDTH * 4);
                }

                for (i = BLANK_OFFSET; i < SCREEN_HEIGHT - BLANK_OFFSET; i++)
                {
                    memcpy(fbp + i * SCREEN_WIDTH * 4, osdBuf + i * SCREEN_WIDTH * 4, FACTORY_DISPLAY_WIDTH * 4);
                    memcpy(fbp + ((i + 1) * SCREEN_WIDTH - BLANK_OFFSET) * 4, osdBuf + ((i + 1) * SCREEN_WIDTH - BLANK_OFFSET) * 4, BLANK_OFFSET * 4);
                }

                for (i = SCREEN_HEIGHT - BLANK_OFFSET; i < SCREEN_HEIGHT; i++) // copy but 2 rows to fbp
                {
                    memcpy(fbp + i * SCREEN_WIDTH * 4, osdBuf + i * SCREEN_WIDTH * 4, SCREEN_WIDTH * 4);
                }
                break;

            case 1: // Full mode
                for (i = 0; i < SCREEN_HEIGHT; i++)
                {
                    // memcpy(fbp+(i*SCREEN_WIDTH*4) + (400*4), osdBuf+ (i*SCREEN_WIDTH*4) + (400 * 4),(SCREEN_WIDTH - 400 -200)*4);   //前面空400像素,拷贝中间1320像素,后面空200像素,
                    memcpy(fbp + (i * SCREEN_WIDTH * 4) + (400 * 4), osdBuf + (i * SCREEN_WIDTH * 4) + (400 * 4), (SCREEN_WIDTH - 400) * 4); //前面空400像素,拷贝后面1520像素
                }
                break;

            case 2: // play mode
                for (i = 0; i < SCREEN_HEIGHT; i++)
                {
                    memset(fbp + (i * SCREEN_WIDTH) * 4, 0, DISPLAY_WIDTH * 4);
                }
                break;

            case 3: // No Video mode
                memcpy(fbp, osdBuf, SCREEN_WIDTH * SCREEN_HEIGHT * 4);
                break;

            case 4: // HDMI display mode
                memcpy(fbp, osdBufHdmi, 1920 * 1080 * 4);
                break;
            }
        }
        cnt++;
    }

//=======================================================================================================
// 获取图像
//=======================================================================================================
int mppFrameGet(int vpssChn, int vpssGrp, VIDEO_FRAME_INFO_S *pstFrameInfom)
    {
        int s32Ret = -1;
        VPSS_CHN_ATTR_S stChnAttr;
        s32Ret = HI_MPI_VPSS_GetChnAttr(vpssGrp, vpssChn, &stChnAttr);
        if (s32Ret != 0)
        {
            printf("%s %d HI_MPI_VI_GetFrameDepth err=%#x\n", __FUNCTION__, __LINE__, s32Ret);
            return -1;
        }
        if (stChnAttr.u32Depth == 0)
        {
            stChnAttr.u32Depth = 1;
            s32Ret = HI_MPI_VPSS_SetChnAttr(vpssGrp, vpssChn, &stChnAttr);
            if (s32Ret != 0)
            {
                printf("%s %d HI_MPI_VI_SetFrameDepth err=%#x\n", __FUNCTION__, __LINE__, s32Ret);
                return -2;
            }
        }

        s32Ret = HI_MPI_VPSS_GetChnFrame(vpssGrp, vpssChn, pstFrameInfom, 500);
        if (s32Ret != 0)
        {
            printf("Funcation:%s Line=%d index  HI_MPI_VI_GetFrame err=%#x\n", __FUNCTION__, __LINE__, s32Ret);
            nosignal = 1;
//------------------------------------------------------------------------------------------------------
//20230414--静电打死时,自动回复,
#if 1
            int connect_device  = GetIniKeyInt("Option","connect_device",PARAM_FILE); //1=OV6946,2=OS01A
            if(connect_device == 2)
            {
                //OS01A--重新初始化--MIPI摄像头;
                PutIniKeyInt("Option","connect_device",connect_device,PARAM_FILE);
                mppSensorChange(connect_device);
                PutIniKeyInt("Option","connect_device",connect_device,PARAM_FILE); 
            }
            else if(connect_device == 1)
            {
                //ov426--重新初始化--DVP摄像头;
                PutIniKeyInt("Option","connect_device",connect_device,PARAM_FILE);
                mppSensorChange(connect_device);
                PutIniKeyInt("Option","connect_device",connect_device,PARAM_FILE);
            }
#endif
//------------------------------------------------------------------------------------------------------
            return -3;
        }
        else
            nosignal = 0;
        return 0;
    }

//=======================================================================================================
// 图像显示出来,拍照时logo图片的显示
//=======================================================================================================
int mppFramePut(int vpssChn, int vpssGrp, int photo, VIDEO_FRAME_INFO_S *pstFrameInfom)
{
    static int flag = 0;
    if (photo)
    {
        if (flag == 0)
        {
           // picUpdateOne    (PHOTO_X, PHOTO_Y, PHOTO_F_WIDTH, PHOTO_F_HEIGHT, image_photo, osdBuf,   3); //显示拍照图标--MIPI
           // picUpdateOneHdmi(PHOTO_X, PHOTO_Y, PHOTO_F_WIDTH, PHOTO_F_HEIGHT, image_photo, ucguiBuf, 3); //显示拍照图标--HDMI
        }
        flag = 1;
    }
    if (flag > 0)
    {
        flag++;
        if (flag > 15)
        {
          //  picUpdateOne(PHOTO_X, PHOTO_Y, PHOTO_F_WIDTH, PHOTO_F_HEIGHT, image_photo, osdBuf,       2); //隐藏拍照图标--MIPI
          //  picUpdateOneHdmi(PHOTO_X, PHOTO_Y, PHOTO_F_WIDTH, PHOTO_F_HEIGHT, image_photo, ucguiBuf, 2); //隐藏拍照图标--HDMI
            flag = 0;
        }
    }
    HI_MPI_VO_SendFrame(0, 0, pstFrameInfom, 1000);
    HI_MPI_VPSS_ReleaseChnFrame(vpssGrp, vpssChn, pstFrameInfom);
    return HI_SUCCESS;
}

//=======================================================================================================
//IVE
//=======================================================================================================
int mppFrameIveGetSrc(VIDEO_FRAME_INFO_S *pstFrameInfom, IVE_SRC_IMAGE_S *pstSrcImg)
    {
        pstSrcImg->enType = IVE_IMAGE_TYPE_YUV420SP;
        pstSrcImg->au64PhyAddr[0] = pstFrameInfom->stVFrame.u64PhyAddr[0];
        pstSrcImg->au64PhyAddr[1] = pstFrameInfom->stVFrame.u64PhyAddr[1];
        pstSrcImg->au64PhyAddr[2] = pstFrameInfom->stVFrame.u64PhyAddr[2];
        pstSrcImg->au64VirAddr[0] = pstFrameInfom->stVFrame.u64VirAddr[0];
        pstSrcImg->au64VirAddr[1] = pstFrameInfom->stVFrame.u64VirAddr[1];
        pstSrcImg->au64VirAddr[2] = pstFrameInfom->stVFrame.u64VirAddr[2];
        pstSrcImg->au32Stride[0] = pstFrameInfom->stVFrame.u32Stride[0];
        pstSrcImg->au32Stride[1] = pstFrameInfom->stVFrame.u32Stride[1];
        pstSrcImg->au32Stride[2] = pstFrameInfom->stVFrame.u32Stride[2];
        pstSrcImg->u32Width = pstFrameInfom->stVFrame.u32Width;
        pstSrcImg->u32Height = pstFrameInfom->stVFrame.u32Height;
        return HI_SUCCESS;
    }

//=======================================================================================================
// YUV-->RGB,  没有使用
//=======================================================================================================
int mppFrameYUV2RGB(VIDEO_FRAME_INFO_S *pstFrameInfom, IVE_SRC_IMAGE_S *pstSrcImg, IVE_SRC_IMAGE_S *pstDstImg)
    {
        HI_BOOL bFinish;
        unsigned int u32Size = 0;
        IVE_HANDLE IveHandle;
        IVE_CSC_CTRL_S stCscCtrl;
        HI_U64 pPhyDst[3] = {0};
        HI_VOID *pVirtDst[3] = {NULL, NULL, NULL};
        u32Size = pstFrameInfom->stVFrame.u32Stride[0] * pstFrameInfom->stVFrame.u32Height;

        HI_MPI_SYS_MmzAlloc(&pPhyDst[0], &pVirtDst[0], "user1", HI_NULL, u32Size);
        HI_MPI_SYS_MmzAlloc(&pPhyDst[1], &pVirtDst[1], "user2", HI_NULL, u32Size);
        HI_MPI_SYS_MmzAlloc(&pPhyDst[2], &pVirtDst[2], "user3", HI_NULL, u32Size);

        pstSrcImg->enType = IVE_IMAGE_TYPE_YUV420SP;
        pstSrcImg->au64PhyAddr[0] = pstFrameInfom->stVFrame.u64PhyAddr[0];
        pstSrcImg->au64PhyAddr[1] = pstFrameInfom->stVFrame.u64PhyAddr[1];
        pstSrcImg->au64PhyAddr[2] = pstFrameInfom->stVFrame.u64PhyAddr[2];
        pstSrcImg->au64VirAddr[0] = pstFrameInfom->stVFrame.u64VirAddr[0];
        pstSrcImg->au64VirAddr[1] = pstFrameInfom->stVFrame.u64VirAddr[1];
        pstSrcImg->au64VirAddr[2] = pstFrameInfom->stVFrame.u64VirAddr[2];
        pstSrcImg->au32Stride[0] = pstFrameInfom->stVFrame.u32Stride[0];
        pstSrcImg->au32Stride[1] = pstFrameInfom->stVFrame.u32Stride[1];
        pstSrcImg->au32Stride[2] = pstFrameInfom->stVFrame.u32Stride[2];
        pstSrcImg->u32Width = pstFrameInfom->stVFrame.u32Width;
        pstSrcImg->u32Height = pstFrameInfom->stVFrame.u32Height;

        pstDstImg->enType = IVE_IMAGE_TYPE_U8C3_PLANAR;
        pstDstImg->au64PhyAddr[0] = pPhyDst[0];
        pstDstImg->au64PhyAddr[1] = pPhyDst[1];
        pstDstImg->au64PhyAddr[2] = pPhyDst[2];
        pstDstImg->au64VirAddr[0] = (HI_U64)(HI_UL)pVirtDst[0];
        pstDstImg->au64VirAddr[1] = (HI_U64)(HI_UL)pVirtDst[1];
        pstDstImg->au64VirAddr[2] = (HI_U64)(HI_UL)pVirtDst[2];
        pstDstImg->au32Stride[0] = pstFrameInfom->stVFrame.u32Stride[0];
        pstDstImg->au32Stride[1] = pstFrameInfom->stVFrame.u32Stride[1];
        pstDstImg->au32Stride[2] = pstFrameInfom->stVFrame.u32Stride[2];
        pstDstImg->u32Width = pstFrameInfom->stVFrame.u32Width;
        pstDstImg->u32Height = pstFrameInfom->stVFrame.u32Height;

        stCscCtrl.enMode = IVE_CSC_MODE_VIDEO_BT601_YUV2RGB;
        HI_MPI_IVE_CSC(&IveHandle, pstSrcImg, pstDstImg, &stCscCtrl, HI_TRUE);
        HI_MPI_IVE_Query(IveHandle, &bFinish, HI_TRUE);
        return 0;
    }

//=======================================================================================================
// RGB-->YUV,  没有使用
//=======================================================================================================
int mppFrameRGB2YUV(VIDEO_FRAME_INFO_S *pstFrameInfom, IVE_SRC_IMAGE_S *pstSrcImg, IVE_SRC_IMAGE_S *pstDstImg)
    {
        HI_BOOL bFinish;
        unsigned int u32Size = 0;
        IVE_HANDLE IveHandle;
        IVE_CSC_CTRL_S stCscCtrl;
        HI_U64 pPhyDst[3] = {0};
        HI_VOID *pVirtDst[3] = {NULL, NULL, NULL};
        u32Size = pstFrameInfom->stVFrame.u32Stride[0] * pstFrameInfom->stVFrame.u32Height;
        HI_MPI_SYS_MmzAlloc(&pPhyDst[0], &pVirtDst[0], "user4", HI_NULL, u32Size);
        HI_MPI_SYS_MmzAlloc(&pPhyDst[1], &pVirtDst[1], "user5", HI_NULL, u32Size);
        HI_MPI_SYS_MmzAlloc(&pPhyDst[2], &pVirtDst[2], "user6", HI_NULL, u32Size);

        pstDstImg->enType = IVE_IMAGE_TYPE_YUV420SP;
        pstDstImg->au64PhyAddr[0] = pPhyDst[0];
        pstDstImg->au64PhyAddr[1] = pPhyDst[1];
        pstDstImg->au64PhyAddr[2] = pPhyDst[2];
        pstDstImg->au64VirAddr[0] = (HI_U64)(HI_UL)pVirtDst[0];
        pstDstImg->au64VirAddr[1] = (HI_U64)(HI_UL)pVirtDst[1];
        pstDstImg->au64VirAddr[2] = (HI_U64)(HI_UL)pVirtDst[2];
        pstDstImg->au32Stride[0] = pstFrameInfom->stVFrame.u32Stride[0];
        pstDstImg->au32Stride[1] = pstFrameInfom->stVFrame.u32Stride[1];
        pstDstImg->au32Stride[2] = pstFrameInfom->stVFrame.u32Stride[2];
        pstDstImg->u32Width = pstFrameInfom->stVFrame.u32Width;
        pstDstImg->u32Height = pstFrameInfom->stVFrame.u32Height;

        stCscCtrl.enMode = IVE_CSC_MODE_VIDEO_BT601_RGB2YUV;
        HI_MPI_IVE_CSC(&IveHandle, pstSrcImg, pstDstImg, &stCscCtrl, HI_TRUE);
        HI_MPI_IVE_Query(IveHandle, &bFinish, HI_TRUE);
        return 0;
    }

//=======================================================================================================
// 写一个信息
//=======================================================================================================
int myisspace(char *p, char *buf)
    {
        int begin = 0;
        int end = strlen(p) - 1;
        int len = 0;
        if (p == NULL || buf == NULL)
        {
            return -1;
        }
        while (isspace(p[begin]) && p[begin] != '\0') //当前字符为空格，且不是字符串结尾
        {
            begin++;
        }
        while (isspace(p[end]) && p[end] != '\0') //当前字符为空格，且不是字符串结尾
        {
            end--;
        }
        len = end - begin + 1;
        strncpy(buf, p + begin, len);
        buf[len] = '\0'; // 补充字符串结束符'\0'
        return 0;
    }

//=======================================================================================================
//读取配置参数文件  para.ini 文件内的某些参数--------------------------------------------- [main.c step 1.1.0]
//=======================================================================================================
int ReadCfgFile(char *CfgFile, char *key, char *value, int *valueLen)
    {
        FILE *fp = NULL;
        char lineBuf[128] = {0};
        char valueBuf[128] = {0};
        char *tmp = NULL;
        int ret = 0;
        int flag = 0;

        if (CfgFile == NULL || key == NULL || value == NULL || valueLen == NULL)
        {
            return -1;
        }
        fp = fopen(CfgFile, "rb");
        if (NULL == fp)
        {
            perror("CfgFile fopen");
            ret = -2;
            goto End;
        }
        while (!feof(fp))
        {
            if (fgets(lineBuf, sizeof(lineBuf), fp) == NULL) //读一行数据，并判断是否到文件结尾
            {
                break;
            }
            tmp = strstr(lineBuf, key);

            if (tmp == NULL)
            {
                continue; //这一行没有key值，并不代表下一行没有，跳出本次循环用continue，而不是用break
            }
            else
            {
                tmp = strstr(lineBuf, "=");
                ; //重新设置起始点

                if (tmp == NULL)
                {
                    continue; //这一行没有=值，并不代表下一行没有，跳出本次循环用continue，而不是用break
                }

                tmp = tmp + strlen("="); //重新设置起始点

                ret = myisspace(tmp, valueBuf); //建议使用两头堵模型通过isspace函数抽取纯字符，否则的话单纯fgets得到的最终value字符和valueLen长度可能包含换行符\r\n
                if (ret != 0)
                {
                    continue; //这一行没有=值，并不代表下一行没有，跳出本次循环用continue，而不是用break
                }
                *valueLen = strlen(valueBuf);
                strcpy(value, valueBuf);
                flag = 1;
                break;
            }
        }
        if (flag == 0)
        {
            printf("配置文件中没有%s作为key值", key);
            ret = -3;
            goto End;
        }
    End:
        if (fp != NULL)
        {
            fclose(fp);
            fp = NULL;
        }
        return ret;
    }

//=======================================================================================================
//读取配置参数文件  para.ini 文件内的某些参数
//=======================================================================================================
char *GetIniKeyString(char *title, char *key, char *filename)
    {
        FILE *fp;
        int flag = 0;
        char sTitle[32], *wTmp;
        static char sLine[1024];

        sprintf(sTitle, "[%s]", title);
        if (NULL == (fp = fopen(filename, "r")))
        {
            perror("fopen");    //打印一个fopen系统错误信息
            return NULL;
        }

        while (NULL != fgets(sLine, 1024, fp))
        { //
            // 这是注释行
            if (0 == strncmp("//", sLine, 2))
                continue;
            if ('#' == sLine[0])
                continue;

            wTmp = strchr(sLine, '=');
            if ((NULL != wTmp) && (1 == flag))
            {
                if (0 == strncmp(key, sLine, wTmp - sLine))
                { // 长度依文件读取的为准
                    sLine[strlen(sLine) - 1] = '\0';
                    fclose(fp);
                    return wTmp + 1;
                }
            }
            else
            {
                if (0 == strncmp(sTitle, sLine, strlen(sLine) - 1))
                {             // 长度依文件读取的为准
                    flag = 1; // 找到标题位置
                }
            }
        }
        fclose(fp);
        return NULL;
    }

//=======================================================================================================
// new
//=======================================================================================================
int GetIniKeyInt(char *title, char *key, char *filename)
    {
        char *str;
        str = GetIniKeyString(title, key, filename);
        return (str == NULL) ? PARAM_NO_EXIST_PARAM : atoi(str);
    }

//=======================================================================================================
// new
//=======================================================================================================
int PutIniKeyString(char *title, char *key, char *val, char *filename)
    {
        FILE *fpr, *fpw;
        int flag = 0;
        char sLine[1024], sTitle[32], *wTmp;

        sprintf(sTitle, "[%s]", title);
        if (NULL == (fpr = fopen(filename, "r")))
            perror("fopen"); // 读取原文件
        sprintf(sLine, "%s.tmp", filename);
        if (NULL == (fpw = fopen(sLine, "w")))
            perror("fopen"); // 写入临时文件

        while (NULL != fgets(sLine, 1024, fpr))
        {
            if (2 != flag)
            { // 如果找到要修改的那一行，则不会执行内部的操作
                wTmp = strchr(sLine, '=');
                if ((NULL != wTmp) && (1 == flag))
                {
                    if (0 == strncmp(key, sLine, wTmp - sLine))
                    {             // 长度依文件读取的为准
                        flag = 2; // 更改值，方便写入文件
                        sprintf(wTmp + 1, "%s\n", val);
                    }
                }
                else if (flag == 0)
                {
                    if (0 == strncmp(sTitle, sLine, strlen(sLine) - 1))
                    { // 长度依文件读取的为准
                        flag = strlen(sLine) - 1 ? 1 : 0;
                    }
                }
            }
            fputs(sLine, fpw); // 写入临时文件
        }
        switch (flag)
        {
        case 0:
            sprintf(sLine, "[%s]\n", title);
            fputs(sLine, fpw); // 写入临时文件
            sprintf(sLine, "%s=%s\n", key, val);
            fputs(sLine, fpw); // 写入临时文件
            break;
        case 1:
            sprintf(sLine, "%s=%s\n", key, val);
            fputs(sLine, fpw); // 写入临时文件
            break;
        }
        fclose(fpr);
        fclose(fpw);
        sprintf(sLine, "%s.tmp", filename);
        return rename(sLine, filename); // 将临时文件更新到原文件
    }

//=======================================================================================================
// new
//=======================================================================================================
int PutIniKeyInt(char *title, char *key, int val, char *filename)
    {
        char sVal[32];
        sprintf(sVal, "%d", val);
        return PutIniKeyString(title, key, sVal, filename);
    }

//=======================================================================================================
// new 读取参数配置文件,如果没有键值 则设置默认参数
//=======================================================================================================
int read_osd_parameter_key(char *id, char *idx, int default_value)
    {
        if (GetIniKeyInt(id, idx, PARAM_FILE) != PARAM_NO_EXIST_PARAM)
            return GetIniKeyInt(id, idx, PARAM_FILE);
        else
        {
            PutIniKeyInt(id, idx, default_value, PARAM_FILE);
            return default_value;
        }
    }

//=======================================================================================================
// new
//=======================================================================================================
int file_exist(char *path)
    {
        int fd = open(path, O_RDONLY);
        return (fd > 0) ? 1 : 0;
    }

//=======================================================================================================
// new
//=======================================================================================================
int mkdirs(char *path)
    {
        char str[512];
        strncpy(str, path, 512);
        int len = strlen(str);
        for (int i = 0; i < len; i++)
        {
            if (str[i] == '/')
            {
                str[i] = '\0';
                if (access(str, 0) != 0)
                    mkdir(str, 0755);
                str[i] = '/';
            }
        }
        if (len > 0 && access(str, 0) != 0)
        {
            mkdir(str, 0755);
        }
        struct stat s;
        stat(path, &s);
        if (S_ISDIR(s.st_mode))
            return 0;
        return 1;
    }


//=======================================================================================================
//=======================================================================================================
int mppFrameCopy(IVE_SRC_IMAGE_S *pstSrcImg, IVE_SRC_IMAGE_S *pstDstImg)
    {
        int j;
        HI_BOOL bFinish;
        IVE_DMA_CTRL_S stDmaCtrl;
        IVE_HANDLE IveHandle;
        IVE_DATA_S stIveDataSrc, stIveDataDst;
        for (j = 0; j < 2; j++)
        {
            stIveDataSrc.u32Height = pstSrcImg->u32Height;
            stIveDataSrc.u32Width = pstSrcImg->u32Width;
            stIveDataSrc.u32Stride = pstSrcImg->au32Stride[j];
            stIveDataSrc.u64PhyAddr = pstSrcImg->au64PhyAddr[j];
            stIveDataSrc.u64VirAddr = pstSrcImg->au64VirAddr[j];
            stIveDataDst.u32Height = pstDstImg->u32Height;
            stIveDataDst.u32Width = pstDstImg->u32Width;
            stIveDataDst.u32Stride = pstDstImg->au32Stride[j];
            stIveDataDst.u64PhyAddr = pstDstImg->au64PhyAddr[j];
            stIveDataDst.u64VirAddr = pstDstImg->au64VirAddr[j];
            stDmaCtrl.enMode = IVE_DMA_MODE_DIRECT_COPY;
            HI_MPI_IVE_DMA(&IveHandle, &stIveDataSrc, &stIveDataDst, &stDmaCtrl, HI_TRUE);
            HI_MPI_IVE_Query(IveHandle, &bFinish, HI_TRUE);
        }
        return HI_SUCCESS;
    }

//=======================================================================================================
//=======================================================================================================
int mppFrameFree(IVE_SRC_IMAGE_S *pstImg)
{
    int j;
    for (j = 0; j < 3; j++)
    {
        HI_MPI_SYS_MmzFree(pstImg->au64PhyAddr[j], (HI_VOID *)(HI_UL)(pstImg->au64VirAddr[j]));
    }
    return HI_SUCCESS;
}

//=======================================================================================================
// 配置VI通道，图像的裁切大小， 图像的旋转控制  本文夹下的main.c文件内调用--------------------- [main.c step 2.4.1]
//=======================================================================================================
void mppFrameRotate(int mode)
{
    ROTATION_E penRotation;
    HI_MPI_VI_GetChnRotation(0, 0, &penRotation);
    switch (mode)
    {
        case 0: penRotation = ROTATION_0; break;
        case 1: penRotation = ROTATION_90; break;
        case 2: penRotation = ROTATION_180; break;
        case 3: penRotation = ROTATION_270; break;
        default: break;
    }
    HI_MPI_VI_SetChnRotation(0, 0, penRotation);
}

//=======================================================================================================
// new
//=======================================================================================================
void mppFrameMirror(int mode)
{
    VI_CHN_ATTR_S stViChnAttr;
    HI_MPI_VI_GetChnAttr(0, 0, &stViChnAttr);
    switch (mode)
    {
    case 0:
        stViChnAttr.bMirror = HI_FALSE; //左右镜像--关闭
        stViChnAttr.bFlip = HI_TRUE;    //上下反转--开启
        break;
    case 1:
        stViChnAttr.bMirror = HI_TRUE;  //左右镜像--开启
        stViChnAttr.bFlip = HI_FALSE;   //上下反转--关闭
        break;
    case 2:
        stViChnAttr.bMirror = HI_TRUE;  //左右镜像--开启
        stViChnAttr.bFlip = HI_TRUE;    //上下反转--开启
        break;
    case 3:
        stViChnAttr.bMirror = HI_FALSE; //左右镜像--关闭
        stViChnAttr.bFlip = HI_FALSE;   //上下反转--关闭
        break;
    }
    HI_MPI_VI_SetChnAttr(0, 0, &stViChnAttr);
}


//=======================================================================================================
// new
//=======================================================================================================
void mppFrameScale()
{
    // mppOsdInit();//修改尺寸同理
    #if 0
    SAMPLE_COMM_VO_StopVO(&stVoConfig);
    SAMPLE_COMM_VO_StartVO(&stVoConfig);
    #else
    // VO的属性配置
    VO_CHN_ATTR_S stChnAttr;
    hdmi_disp_mode = read_osd_parameter_key("Option", "display_set", 1);
    hdmi_size = read_osd_parameter_key("Option", "Size", 3);
    if(stViConfig.astViInfo[0].stDevInfo.ViDev == 0)
    {
        if(hdmi_size <3)
            hdmi_size = 3;          //xwc if camera is os01a ,then make the hdmi_size to be 800x800
        mppOsdInit();
    }
    switch(hdmi_disp_mode)
    {
        case HDMI_1080P:
            switch (hdmi_size) //视频流的大小设置，HDMI模块（VO通道内)有缩放功能, 与VI 通道内的图像长宽参数独立。
            {
            case 1:
                stChnAttr.stRect.s32X = 760;
                stChnAttr.stRect.s32Y = 340;
                stChnAttr.stRect.u32Width = 400;
                stChnAttr.stRect.u32Height = 400;
                break;
            case 2:
                stChnAttr.stRect.s32X = 660;
                stChnAttr.stRect.s32Y = 240;
                stChnAttr.stRect.u32Width = 600;
                stChnAttr.stRect.u32Height = 600;
                break;
            case 3:
                stChnAttr.stRect.s32X = 560;
                stChnAttr.stRect.s32Y = 140;
                stChnAttr.stRect.u32Width = 800;
                stChnAttr.stRect.u32Height = 800;
                break;
            case 4:
                stChnAttr.stRect.s32X = 560;
                stChnAttr.stRect.s32Y = 40;
                stChnAttr.stRect.u32Width = 1000;
                stChnAttr.stRect.u32Height = 1000;
                break;
            default:
                break;
            }
        break;
        case HDMI_1920x1200:
            switch (hdmi_size) //视频流的大小设置，HDMI模块（VO通道内)有缩放功能, 与VI 通道内的图像长宽参数独立。
            {
            case 1:
                stChnAttr.stRect.s32X = 760;
                stChnAttr.stRect.s32Y = 340;
                stChnAttr.stRect.u32Width = 400;
                stChnAttr.stRect.u32Height = 400;
                break;
            case 2:
                stChnAttr.stRect.s32X = 660;
                stChnAttr.stRect.s32Y = 240;
                stChnAttr.stRect.u32Width = 600;
                stChnAttr.stRect.u32Height = 600;
                break;
            case 3:
                stChnAttr.stRect.s32X = 560;
                stChnAttr.stRect.s32Y = 140;
                stChnAttr.stRect.u32Width = 800;
                stChnAttr.stRect.u32Height = 800;
                break;
            case 4:
                stChnAttr.stRect.s32X = 560;
                stChnAttr.stRect.s32Y = 40;
                stChnAttr.stRect.u32Width = 1000;
                stChnAttr.stRect.u32Height = 1000;
                break;
            default:
                break;
            }
        break;

    }
    PutIniKeyInt("Option","Size", hdmi_size,PARAM_FILE);
    printf("Image   Size: %d * %d\n",stChnAttr.stRect.u32Width ,stChnAttr.stRect.u32Height);
    stChnAttr.u32Priority = 0;
    stChnAttr.bDeflicker = HI_FALSE; //关闭视频抗闪烁
    HI_MPI_VO_SetChnAttr(stVoConfig.VoDev, 0, &stChnAttr);
    // HI_MPI_VO_EnableChn(stVoConfig.VoDev, 0);
    #endif
}

//=======================================================================================================
// new---摄像头更改,重新配置摄像头
//=======================================================================================================
void mppSensorChange(int sensor_dev)
{
    HI_U32 u32ViIntfType = 1;
    HI_U32 u32VoIntfType = read_osd_parameter_key("Option", "Size", 3);
    SAMPLE_COMM_VI_StopVi(&stViConfig);
    viVpssDeinit();
    switch (sensor_dev)
    {
        case 1: u32ViIntfType = 1; break; // OV426
        case 2: u32ViIntfType = 0; break; // OS01A
        case 3: u32ViIntfType = 1; break; // UVC
        case 4: u32ViIntfType = 1; break; // RESERVE
    }  
    configInit(u32ViIntfType, u32VoIntfType);//u32VoIntfType);
    SAMPLE_COMM_VI_StartVi(&stViConfig);
    viVpssInit(stViConfig, SCREEN_WIDTH, SCREEN_HEIGHT);
    if (sensor_dev == 1)
    {
        //isp_ctrl();
        mppisp_ov426_ctrl();
        system("sh /usr/qt5.12/demos/sensor_rst.sh > /dev/null");
    }
    else
        mppisp_os01a_ctrl();
}


//=======================================================================================================
// new -- 更改显示器的显示分辨率,
//=======================================================================================================
void mppDisplaySet(int mode)
{
    VO_PUB_ATTR_S stVoPubAttr = {0};
    hdmi_disp_mode = read_osd_parameter_key("Option", "display_set", 1);
    SAMPLE_COMM_VO_StopVO(&stVoConfig);
    switch (mode)
    {

        case 1:
                stVoConfig.enIntfSync = VO_OUTPUT_1080P60;      
                stVoConfig.stImageSize.u32Width = 1920; 
                stVoConfig.stImageSize.u32Height = 1080;
                break;
        case 2:
                stVoConfig.enIntfSync = VO_OUTPUT_1920x1200_60; 
                stVoConfig.stImageSize.u32Width = 1920; 
                stVoConfig.stImageSize.u32Height = 1200;
                break;
        /*
        case 1: 
                stVoConfig.enIntfSync = VO_OUTPUT_1280x1024_60; 
                stVoConfig.stImageSize.u32Width = 1280; 
                stVoConfig.stImageSize.u32Height = 1024;
                break;
        case 2: 
                stVoConfig.enIntfSync = VO_OUTPUT_1920x1200_60; 
                stVoConfig.stImageSize.u32Width = 1920; 
                stVoConfig.stImageSize.u32Height = 1200;
                break;
        case 3: 
                stVoConfig.enIntfSync = VO_OUTPUT_1080P60;      
                stVoConfig.stImageSize.u32Width = 1920; 
                stVoConfig.stImageSize.u32Height = 1080;
                break;
        */
    }
    SAMPLE_COMM_VO_StartVO(&stVoConfig);
}


//=======================================================================================================
//打印调试信息的函数
//=======================================================================================================
void getispinfo()
    {
        ISP_CA_ATTR_S stCAAttr;
        ISP_CLUT_ATTR_S stClutAttr;
        ISP_CR_ATTR_S stCRAttr;
        ISP_DE_ATTR_S stDEAttr;
        ISP_DP_DYNAMIC_ATTR_S stDPDynamicAttr;
        ISP_DP_STATIC_ATTR_S stDPStaticAttr;
        ISP_LDCI_ATTR_S stLDCIAttr;
        ISP_LOCAL_CAC_ATTR_S stLocalCacAttr;
        ISP_NR_ATTR_S stNRAttr;
        ISP_SHADING_ATTR_S stShadingAttr;
        HI_MPI_ISP_GetCAAttr(0, &stCAAttr);               //
        HI_MPI_ISP_GetClutAttr(0, &stClutAttr);           //
        HI_MPI_ISP_GetCrosstalkAttr(0, &stCRAttr);        //
        HI_MPI_ISP_GetDEAttr(0, &stDEAttr);               //
        HI_MPI_ISP_GetDPDynamicAttr(0, &stDPDynamicAttr); //
        HI_MPI_ISP_GetDPStaticAttr(0, &stDPStaticAttr);   //
        HI_MPI_ISP_GetLDCIAttr(0, &stLDCIAttr);           //
        HI_MPI_ISP_GetLocalCacAttr(0, &stLocalCacAttr);   //
        HI_MPI_ISP_GetNRAttr(0, &stNRAttr);               //
        HI_MPI_ISP_GetMeshShadingAttr(0, &stShadingAttr);
        stCAAttr.bEnable = HI_FALSE;
        stClutAttr.bEnable = HI_FALSE;
        stCRAttr.bEnable = HI_FALSE;
        stDEAttr.bEnable = HI_FALSE;
        stDPDynamicAttr.bEnable = HI_FALSE;
        stDPStaticAttr.bEnable = HI_FALSE;
        stLDCIAttr.bEnable = HI_FALSE;
        stLocalCacAttr.bEnable = HI_FALSE;
        stNRAttr.bEnable = HI_FALSE;
        stShadingAttr.bEnable = HI_FALSE;
        HI_MPI_ISP_SetMeshShadingAttr(0, &stShadingAttr);
        HI_MPI_ISP_SetCAAttr(0, &stCAAttr);               //
        HI_MPI_ISP_SetClutAttr(0, &stClutAttr);           //
        HI_MPI_ISP_SetCrosstalkAttr(0, &stCRAttr);        //
        HI_MPI_ISP_SetDEAttr(0, &stDEAttr);               //
        HI_MPI_ISP_SetDPDynamicAttr(0, &stDPDynamicAttr); //
        HI_MPI_ISP_SetDPStaticAttr(0, &stDPStaticAttr);   //
        HI_MPI_ISP_SetLDCIAttr(0, &stLDCIAttr);           //
        HI_MPI_ISP_SetLocalCacAttr(0, &stLocalCacAttr);   //
        HI_MPI_ISP_SetNRAttr(0, &stNRAttr);               //
#if 0
            printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
            stCAAttr.bEnable,stClutAttr.bEnable,stCRAttr.bEnable,stCSCFAttr.bEnable,stDEAttr.bEnable,
            stDehazeAttr.bEnable,stDemosaicAttr.bEnable,stDISAttr.bEnable,stDPDynamicAttr.bEnable,stDPStaticAttr.bEnable,
            stDRC.bEnable,stExpAttr.bByPass,stFPNAttr.bEnable,stGammaAttr.bEnable,stGlobalCacAttr.bEnable,stIrisAttr.bEnable,
            stIspEdgeMarkAttr.bEnable,stIspHlcAttr.bEnable,stIspShpAttr.bEnable,stLDCIAttr.bEnable,stLocalCacAttr.bEnable,
            stLogLUTAttr.bEnable,stShadingAttr.bEnable,stNRAttr.bEnable,stPreGammaAttr.bEnable,stPreLogLUTAttr.bEnable,
            stRaShadingAttr.bEnable,stRcAttr.bEnable,stRGBIRAttr.bEnable,stSmartExpAttr.bEnable);
#endif
    }

//=======================================================================================================
// BLC  sensor的黑电频校正
//=======================================================================================================
// op_type = OP_TYPE_MANUAL   or  OP_TYPE_AUTO
void mppIsp_BLC(HI_S32 ViPipe, SAMPLE_VI_INFO_S *pstViInfo)
    {
        ISP_BLACK_LEVEL_S stBlcAttr;
        HI_MPI_ISP_GetBlackLevelAttr(ViPipe, &stBlcAttr);

        switch (pstViInfo->stSnsInfo.enSnsType)
        {
        case OS01A:
            stBlcAttr.enOpType = OP_TYPE_MANUAL; // MANU
            stBlcAttr.au16BlackLevel[0] = 16;    // R
            stBlcAttr.au16BlackLevel[1] = 16;    // GR
            stBlcAttr.au16BlackLevel[2] = 15;    // GB
            stBlcAttr.au16BlackLevel[3] = 16;    // B
            break;

        case OV426:
            stBlcAttr.enOpType = OP_TYPE_AUTO; // OP_TYPE_AUTO
            break;
        }

        HI_MPI_ISP_SetBlackLevelAttr(ViPipe, &stBlcAttr);
    }


//=======================================================================================================
//手动曝光控制，  可切换成自动曝光方式
//=======================================================================================================
//无论是自动曝光还是手动曝光，曝光时间的单位为微秒(us)，曝光增益的单位为10bit精度的倍数即1024代表1倍,2048代表2倍等。
// mode 0: exptime 1:again 2:dgain 3:ispdgain
// op_type = OP_TYPE_MANUAL   or  OP_TYPE_AUTO
void mppIspAeManual(HI_S32 ViPipe, HI_S32 mode, HI_U8 op_type, HI_S32 data)
    {
        ISP_EXPOSURE_ATTR_S stExpAttr;
        HI_MPI_ISP_GetExposureAttr(ViPipe, &stExpAttr);

        stExpAttr.bByPass = HI_FALSE;
        // stExpAttr.stAuto.stExpTimeRange.u32Max =40000;  //自动曝光时长上限um
        // stExpAttr.stAuto.stExpTimeRange.u32Min =10;     //自动曝光时长下限um
        // stExpAttr.enOpType =OP_TYPE_AUTO;                //AUTO    AE;
        // stExpAttr.enOpType = OP_TYPE_MANUAL;             //MANUAL  AE;
        stExpAttr.enOpType = op_type;
        switch (mode)
        {
        case 0:
            stExpAttr.stManual.enExpTimeOpType = op_type;
            stExpAttr.stManual.u32ExpTime = data; // Range:[0x0, 0xFFFFFFFF]; Format:32.0; sensor exposure time (unit: us ), it's related to the specific sensor
            break;
        case 1:
            stExpAttr.stManual.enAGainOpType = op_type;
            stExpAttr.stManual.u32AGain = data; //范围:[0 x400 0 xffffffff];格式:22.10;传感器模拟增益(单位:倍，10位精度)，它与具体的传感器有关
            break;
        case 2:
            stExpAttr.stManual.enDGainOpType = op_type;
            stExpAttr.stManual.u32DGain = data; //范围:[0 x400 0 xffffffff];格式:22.10;传感器数字增益(单位:倍，10位精度)，与具体的传感器有关
            break;
        case 3:
            stExpAttr.stManual.enISPDGainOpType = op_type;
            stExpAttr.stManual.u32ISPDGain = data; //范围:[0 x400 0 x40000];格式:22.10;ISP数字增益(单位:倍，10位精度)，它与ISP数字增益范围有关; 1024=1;
            break;
        }
        HI_MPI_ISP_SetExposureAttr(ViPipe, &stExpAttr);
    }
//=======================================================================================================
//设置 AE 曝光分配策略,   AEtime-->AEgain HIS 3516dv300 isp
//=======================================================================================================
void mppisp_SetAERouteAttr()
    {
        VI_PIPE ViPipe = 0;
        ISP_AE_ROUTE_S stRoute;
        HI_U32 au32RouteNode[3][3] = {{40, 1024, 1}, {30000, 1024, 1}, {30000, 15360, 1}};
        HI_MPI_ISP_GetAERouteAttr(ViPipe, &stRoute);
        stRoute.u32TotalNum = 3;
        memcpy(stRoute.astRouteNode, au32RouteNode, sizeof(au32RouteNode));
        HI_MPI_ISP_SetAERouteAttr(ViPipe, &stRoute);
    }


//=======================================================================================================
//设置 AE 曝光分配扩展属性策略,   AEtime-->AEgain ;camera isp
//=======================================================================================================
void mppisp_SetAERouteAttrEx()
  {
        VI_PIPE ViPipe = 0;
        ISP_EXPOSURE_ATTR_S stExpAttr;
        ISP_AE_ROUTE_EX_S   stRouteEx;

        //曝光时间、 sensor模拟增益、 sensor数字增益、 ISP数字增益,光圈五个分量
        HI_U32 au32RouteExNode1[4][5]
                                = {{ 40   , 1024,  1024,  1024,  0},
                                   { 30000, 1024,  1024,  1024,  0},
                                   { 30000, 15360, 1024,  1024,  0},
                                   { 30000, 15360, 1024,  5120,  0}};

        HI_MPI_ISP_GetAERouteAttrEx(ViPipe, &stRouteEx);
        HI_MPI_ISP_GetExposureAttr(ViPipe, &stExpAttr);
        // AE 曝光分配扩展属性是否生效可通过配置 HI_MPI_ISP_SetExposureAttr 接口中的 bAERouteExValid 来实现。
        // bAERouteExValid 为 HI_TRUE 时使用扩展 AE route，否则使用正常 AE route。
        stExpAttr.bAERouteExValid = HI_TRUE;//HI_FALSE;

        //时使用扩展 AE route
        stRouteEx.u32TotalNum = 4;
        memcpy(stRouteEx.astRouteExNode, au32RouteExNode1,sizeof(au32RouteExNode1));
        HI_MPI_ISP_SetAERouteAttrEx(ViPipe, &stRouteEx);
        HI_MPI_ISP_SetExposureAttr(ViPipe, &stExpAttr);
    }


//=======================================================================================================
//自动曝光属性设置：mode =0 OP_TYPE_AUTO;       mode=1 OP_TYPE_MANUAL;     mode=2 bByPass;
//=======================================================================================================
//无论是自动曝光还是手动曝光，曝光时间的单位为微秒(us)，曝光增益的单位为10bit精度的倍数即1024代表1倍,2048代表2倍等。
void mppIsp_AUTO_EXPOSURE(VI_PIPE ViPipe, HI_S32 mode)
    {
        //最大支持 16 个节点，每个节点有曝光时间、增益、光圈三个分量，增益包含模拟增益、数字增益、 ISP 数字增益。
        //节点中曝光时间的单位为 us，不能设置为 0，也不能设置太小导致实际对应的曝光行数为 0，否则可能产生异常;
        //节点的曝光量是曝光时间、增益和光圈的乘积，节点曝光量单调递增，后一个节点的曝光量大于或等于前一个节点的曝光量，
        //第一个节点的曝光量最小，最后一个节点的曝光量最大,如果相邻节点的曝光量增加，那么应该有一个分量增加，其他分量固定，
        //增加的分量决定该段路线的分配策略。例如增益分量增加，那么该段路线的分配策略是增益优先。

        ISP_EXP_INFO_S stExpInfo;                       //获取 AE 内部状态信息，
        ISP_EXPOSURE_ATTR_S stExpAttr;                  // AE 曝光属性
        HI_MPI_ISP_GetExposureAttr(ViPipe, &stExpAttr); //获取 AE 曝光属性。

        switch (mode)
        {
        case 0: //自动曝光属性设置：
            //-------------------------------------------------------------------------------------------
            stExpAttr.bByPass = HI_FALSE;
            stExpAttr.enOpType = OP_TYPE_AUTO;

            // AE 曝光分配扩展属性是否生效可通过配置 HI_MPI_ISP_SetExposureAttr 接口中的 bAERouteExValid 来实现。 bAERouteExValid 为 HI_TRUE 时使用扩展 AE route，否则使用正常 AE route。
            stExpAttr.bAERouteExValid = HI_TRUE;//HI_FALSE;
            //mppisp_SetAERouteAttr();            // AE 曝光分配扩展属性
            mppisp_SetAERouteAttrEx();            // AE 曝光分配扩展属性

            //范围:[0x0, 0xffffffff];格式:32.0;传感器曝光时间(单位:us)，与特定的传感器有关
            stExpAttr.stAuto.stExpTimeRange.u32Max  = 40000;   // 30ms;定义曝光时间或增益的Max值um; Range:[0x0, 0xFFFFFFFF]; Format:32.0; sensor exposure time (unit: us ), it's related to the specific sensor
            stExpAttr.stAuto.stExpTimeRange.u32Min  = 40;      // 4ms; 定义曝光时间或增益的Min值um; Range:[0x0, 0xFFFFFFFF]; Format:32.0; sensor exposure time (unit: us ), it's related to the specific sensor
            stExpAttr.stAuto.stAGainRange.u32Max    = 15360;   // 10240=10倍,16383=16倍;    //[0x400 0xffffffff];格式:22.10;传感器模拟增益(单位:倍，10位精度)，与传感器有关
            stExpAttr.stAuto.stAGainRange.u32Min    = 1024;
            stExpAttr.stAuto.stDGainRange.u32Max    = 1024;    // 10240=10倍,16383=16倍;    //[0x400 0xffffffff];格式:22.10;传感器数字增益(单位:倍，10位精度)，与传感器有关
            stExpAttr.stAuto.stDGainRange.u32Min    = 1024;
            stExpAttr.stAuto.stISPDGainRange.u32Max = 5120;    // 5120=5倍分,10240=10倍,16383=16倍; //[0x400 0x40000];格式:22.10;ISP数字增益(单位:倍，10位精度)，与传感器有关
            stExpAttr.stAuto.stISPDGainRange.u32Min = 1024;
            stExpAttr.stAuto.stSysGainRange.u32Max  = 0xFFFF;  //[0x400 0xffffffff];格式:22.10;系统增益(单位:倍，10位精度)，与传感器有关
            stExpAttr.stAuto.stSysGainRange.u32Min  = 1024;
            HI_MPI_ISP_SetExposureAttr(ViPipe, &stExpAttr);   //设置 AE 曝光属性。

            stExpAttr.stAuto.u32GainThreshold = 0xC8000;      // 0xC8000=800倍,[0x400 0xffffffff];格式:22.10;自动降帧时的系统增益门限值(单位:倍，10位精度)
            stExpAttr.stAuto.u8Speed = 150;                   //默认值为0x40 [0-255] 自动曝光调整时的速度
            stExpAttr.stAuto.u16BlackSpeedBias =0x90;         //默认值为0x90 [0x0, 0xffff];格式:16.0;画面由暗到亮 AE 调节速度的偏差值，该值越大，画面从暗到亮的速度越快
            stExpAttr.stAuto.u8Tolerance = 0x2;               //默认值为0x2  [0x0, 0xff];格式:8.0;自动曝光调整时对画面亮度的容忍偏差
            stExpAttr.stAuto.enAEMode = 1;                    //[0,1];格式:1.0;AE模式(0=慢快门/1=固定帧率)(onvif),
            stExpAttr.stAuto.enAEStrategyMode = 0;            //[0,1];0=高光优先/1=低光优先

            stExpAttr.stAuto.u8Compensation = 0x45;           //[0x0, 0xFF]，默认值为 0x38-0X40。自动曝光调整时的目标亮度
            stExpAttr.stAuto.u16EVBias = 0x400;               //取值范围[0x0, 0xFFFF]，默认值为 0x400。自动曝光调整时的曝光量偏差值,10bit小数精度。
            stExpAttr.stAuto.u16HistRatioSlope = 0x80;        //取值范围[0x0, 0xFFFF]，默认值为 0x80。感兴趣区域的权重.
            stExpAttr.stAuto.u8MaxHistOffset = 0x10;          //取值范围[0x0, 0xFF]，默认值为 0x10。感兴趣区域对统计平均值影响的最大程度
            HI_MPI_ISP_SetExposureAttr(ViPipe, &stExpAttr);   //设置 AE 曝光属性。
            
            //抗闪属性设置。默认抗闪不使能。
            stExpAttr.stAuto.stAntiflicker.bEnable = HI_TRUE;
            stExpAttr.stAuto.stAntiflicker.u8Frequency = 50;
            stExpAttr.stAuto.stAntiflicker.enMode = ISP_ANTIFLICKER_AUTO_MODE; // ISP_ANTIFLICKER_NORMAL_MODE;

            // 延迟XX帧调整曝光
            stExpAttr.stAuto.stAEDelayAttr.u16BlackDelayFrame = 2;//3;//6; //图像亮度小于目标亮度时间超过 u16BlackDelayFrame 帧时，AE 开始调节.
            stExpAttr.stAuto.stAEDelayAttr.u16WhiteDelayFrame = 0;//1;//2; //图像亮度大于目标亮度时间超过 u16WhiteDelayFrame 帧时，AE 开始调节.
            HI_MPI_ISP_SetExposureAttr(ViPipe, &stExpAttr);             //设置 AE 曝光属性。

            #if 0
                    HI_MPI_ISP_QueryExposureInfo(ViPipe, &stExpInfo);           //获取 AE 内部状态信息，
                    printf("ISP_INFO::*****************************************\n");
                    printf("ISP_INFO::u32ExpTime        = %d\n",stExpInfo.u32ExpTime);
                    printf("ISP_INFO::u32ShortExpTime   = %d\n",stExpInfo.u32ShortExpTime);
                    printf("ISP_INFO::u32MedianExpTime  = %d\n",stExpInfo.u32MedianExpTime);
                    printf("ISP_INFO::u32LongExpTime    = %d\n",stExpInfo.u32LongExpTime);
                    printf("ISP_INFO::u32AGain          = %d\n",stExpInfo.u32AGain);
                    printf("ISP_INFO::u32DGain          = %d\n",stExpInfo.u32DGain);
                    printf("ISP_INFO::u32ISPDGain       = %d\n",stExpInfo.u32ISPDGain);
                    printf("ISP_INFO::u32Exposure       = %d\n",stExpInfo.u32Exposure);
                    printf("ISP_INFO::s16HistError      = %d\n",stExpInfo.s16HistError);
                    printf("ISP_INFO::bExposureIsMAX    = %d\n",stExpInfo.bExposureIsMAX);
                    printf("ISP_INFO::u8AveLum            = %d\n",stExpInfo.u8AveLum);
                    printf("ISP_INFO::u32LinesPer500ms  = %d\n",stExpInfo.u32LinesPer500ms);
                    printf("ISP_INFO::u32PirisFNO       = %d\n",stExpInfo.u32PirisFNO);
                    printf("ISP_INFO::u32Fps            = %d\n",stExpInfo.u32Fps);
                    printf("ISP_INFO::u32ISO            = %d\n",stExpInfo.u32ISO);
                    printf("ISP_INFO::u32ISOCalibrate   = %d\n",stExpInfo.u32ISOCalibrate);
                    printf("ISP_INFO::bExposureIsMAX    = %d\n",stExpInfo.bExposureIsMAX);
            #endif
            break;

        case 1: //手动曝光属性设置：
            //-------------------------------------------------------------------------------------------
            stExpAttr.bByPass = HI_FALSE;
            stExpAttr.enOpType = OP_TYPE_MANUAL;
            stExpAttr.stManual.enAGainOpType    = OP_TYPE_MANUAL;
            stExpAttr.stManual.enDGainOpType    = OP_TYPE_MANUAL;
            stExpAttr.stManual.enISPDGainOpType = OP_TYPE_MANUAL;
            stExpAttr.stManual.enExpTimeOpType  = OP_TYPE_MANUAL;

            stExpAttr.stManual.u32AGain     = 1024;
            stExpAttr.stManual.u32DGain     = 1024;
            stExpAttr.stManual.u32ISPDGain  = 1024;
            stExpAttr.stManual.u32ExpTime   = 35000;
            break;

        case 2: // AE bByPass 关闭海思ISP 的自动曝光
            //-------------------------------------------------------------------------------------------
            stExpAttr.bByPass = HI_TRUE;
            break;
        }

        HI_MPI_ISP_SetExposureAttr(ViPipe, &stExpAttr);
    }

//=======================================================================================================
// 关闭海思ISP 的自动曝光AE
//=======================================================================================================
void mppIspAEDisable()
    {
        ISP_EXPOSURE_ATTR_S stExpAttr;
        HI_MPI_ISP_GetExposureAttr(0, &stExpAttr);
        stExpAttr.bByPass = HI_TRUE;
        HI_MPI_ISP_SetExposureAttr(0, &stExpAttr);
        PutIniKeyInt("isp","ae_mode", 2, PARAM_FILE);                    //2 =bypass.
    }

//=======================================================================================================
//设置视频层输出图像效果。
//=======================================================================================================
//该接口主要用于调节图像的输出效果，包括亮度、对比度、色调、饱和度，其取值范围均为[0, 100]
void mppisp_VO_VideoLayerCSC(HI_S32 type, HI_U32 value)
    {
        VO_CSC_S stVoCSCAttr;
        HI_MPI_VO_GetVideoLayerCSC(stVoConfig.VoDev, &stVoCSCAttr);
        // stVoCSCAttr.enCscMatrix = VO_CSC_MATRIX_BT709_TO_RGB_PC;   //VO_CSC_MATRIX_IDENTITY;  //input = output = RGB;
        switch (type)
        {
        case 0:
            stVoCSCAttr.u32Luma = value; //目标 YUV 空间亮度 [0,100]
            break;
        case 1:
            stVoCSCAttr.u32Contrast = value; //目标 YUV 空间对比度 [0,100]
            break;
        case 2:
            stVoCSCAttr.u32Hue = value; //目标 YUV 空间色调  [0,100]
            break;
        case 3:
            stVoCSCAttr.u32Satuature = value; //目标 YUV 空间饱和度 [0,100]
            break;
        }
        HI_MPI_VO_SetVideoLayerCSC(stVoConfig.VoDev, &stVoCSCAttr);
    }

//=======================================================================================================
//设置图形层输出图像效果。
//=======================================================================================================
void mppisp_VO_GraphicLayerCSC(VO_LAYER VoLayer, HI_S32 type, HI_U32 value)
    {
        VO_CSC_S stCSCAttr;
        HI_MPI_VO_GetGraphicLayerCSC(VoLayer, &stCSCAttr);
        stCSCAttr.enCscMatrix = VO_CSC_MATRIX_IDENTITY;
        switch (type)
        {
        case 0:
            stCSCAttr.u32Luma = value; //目标 YUV 空间亮度 [0,100]
            break;
        case 1:
            stCSCAttr.u32Contrast = value; //目标 YUV 空间对比度 [0,100]
            break;
        case 2:
            stCSCAttr.u32Hue = value; //目标 YUV 空间色调 [0,100]
            break;
        case 3:
            stCSCAttr.u32Satuature = value; //目标 YUV 空间饱和度 [0,100]
            break;
        }
        HI_MPI_VO_SetGraphicLayerCSC(VoLayer, &stCSCAttr);
    }

//=======================================================================================================
// YUV CSC 当前未使用此函数,
//=======================================================================================================
void mppIspCscManual(HI_S32 Vipipe, HI_S32 type, HI_U8 v)
    {
        ISP_CSC_ATTR_S stCSCAttr;
        HI_MPI_ISP_GetCSCAttr(Vipipe, &stCSCAttr);

        // stCSCAttr.bEnable = HI_TRUE;    //使能 CSC 功能。[0,1] 0： 禁止；1： 使能。defaut=1
        // stCSCAttr.bLimitedRangeEn = 0;  //目标 YUV 空间动态范围选择[0,1]0： 输出为 Full Range；1： 输出为 Limited Range。
        // stCSCAttr.bCtModeEn=1;          //选择输出的对比度调整模式 [0， 1]   1:改变 u8Contr 画面亮度不会变化
        // stCSCAttr.bExtCscEn=1;          //选择亮度调整模式（与u8Luma 配合）[0， 1] 1:表示 u8Luma 可以调节更宽的亮度变化
        // stCSCAttr.enColorGamut = COLOR_GAMUT_BT709; //色域,彩空间类型枚举[0,4]
        switch (type)
        {
        case 0:
            stCSCAttr.u8Luma = v; //目标 YUV 空间亮度 [0,100]
            break;
        case 1:
            stCSCAttr.u8Contr = v; //目标 YUV 空间对比度 [0,100]
            break;
        case 2:
            stCSCAttr.u8Hue = v; //目标 YUV 空间色调 [0,100]
            break;
        case 3:
            stCSCAttr.u8Satu = v; //目标 YUV 空间饱和度 [0,100]
            break;
        }
        HI_MPI_ISP_SetCSCAttr(0, &stCSCAttr);
    }

//=======================================================================================================
// ISP_AWB  0:Auto   1: calgainByTemp  2:MWB
//=======================================================================================================
void mppIspAwb(HI_S32 ViPipe, HI_U8 mode, HI_U16 u16ColorTemp, HI_U16 Rgain, HI_U16 Grgain, HI_U16 Gbgain, HI_U16 Bgain)
    {
        ISP_WB_ATTR_S stWBAttr;
        HI_U16 u16AWBGain[4];
        HI_MPI_ISP_GetWBAttr(ViPipe, &stWBAttr);
        switch (mode)
        {
        case 0:
            stWBAttr.enOpType = OP_TYPE_AUTO;
            break;
        case 1:
            HI_MPI_ISP_CalGainByTemp(ViPipe, &stWBAttr, u16ColorTemp, 0, u16AWBGain);
            stWBAttr.enOpType = OP_TYPE_MANUAL;
            memcpy(&stWBAttr.stManual, u16AWBGain, sizeof(stWBAttr.stManual));
            break;
        case 2:
            stWBAttr.enOpType = OP_TYPE_MANUAL;
            stWBAttr.stManual.u16Rgain = Rgain;   /*RW; Range: [0x0, 0xFFF]; Format:4.8; Multiplier for R   color channel  */
            stWBAttr.stManual.u16Grgain = Grgain; /*RW; Range: [0x0, 0xFFF]; Format:4.8; Multiplier for Gr  color channel  */
            stWBAttr.stManual.u16Gbgain = Gbgain; /*RW; Range: [0x0, 0xFFF]; Format:4.8; Multiplier for Gb  color channel  */
            stWBAttr.stManual.u16Bgain = Bgain;   /*RW; Range: [0x0, 0xFFF]; Format:4.8; Multiplier for B   color channel  */
            break;
        }
        HI_MPI_ISP_SetWBAttr(ViPipe, &stWBAttr);
    }

/*===============================================================================================================
* Sharpen 模块用于增强图像的清晰度，包括调节图像边缘的锐化属性和增强图像的细节和纹理的清晰度，同时还能分别独立控制图像的带方向的边缘
* 和无方向的细节纹理的锐化强度。此外，还能控制锐化后的图像的 overshoot（白边白点）和 undershoot（黑边黑点），以及抑制噪声的增强。
===============================================================================================================*/
// ISP  图像增强锐化 ，  --> browseform.cpp 内进行的调用
//具体参数在，，   /etc/water mask/para.ini(编译后的文件系统内)
void mppIspSharpen(HI_S32 ViPipe, HI_U8 mode, HI_U16 TextureFreq, HI_U16 EdgeFreq, HI_U8 Overshoot, HI_U8 UnderShoot,
                       HI_U8 umax, HI_U8 umin, HI_U8 vmax, HI_U8 vmin, HI_U8 luma, HI_U16 texturestr, HI_U16 edgestr, HI_U8 supstr,
                       HI_U8 supadj, HI_U8 detailctrl, HI_U8 detailctrlthr, HI_U8 edgefilt, HI_U8 rgain, HI_U8 ggain, HI_U8 bgain,
                       HI_U8 skingain, HI_U16 maxsharp)
    {
        int i;
        ISP_SHARPEN_ATTR_S stIspShpAttr;
        HI_MPI_ISP_GetIspSharpenAttr(ViPipe, &stIspShpAttr);
        switch (mode)
        {
        case 0:
            stIspShpAttr.enOpType = OP_TYPE_AUTO;
            break;
        case 1:
            stIspShpAttr.enOpType = OP_TYPE_MANUAL;
            stIspShpAttr.stManual.u16TextureFreq = TextureFreq; //细节纹理强度 0-4095,值越大，图像锐化程度越高，反之，越弱。
            stIspShpAttr.stManual.u16EdgeFreq = EdgeFreq;       //边缘锐化强度 0-4095
            stIspShpAttr.stManual.u8OverShoot = Overshoot;      //白点锐化强度 0-127
            stIspShpAttr.stManual.u8UnderShoot = UnderShoot;    //黑点锐化强度 0-127
            break;
        case 2:
            stIspShpAttr.enOpType = OP_TYPE_MANUAL;
            stIspShpAttr.u8SkinUmax = umax; // 0 - 255
            stIspShpAttr.u8SkinUmin = umin; // 0 - 255
            stIspShpAttr.u8SkinVmax = vmax; // 0 - 255
            stIspShpAttr.u8SkinVmin = vmin; // 0 - 255
            for (i = 0; i < ISP_SHARPEN_LUMA_NUM; i++)
            {
                stIspShpAttr.stManual.au8LumaWgt[i] = luma;           // 0-127     (127) 值越大图像锐化程度越高，反之越弱。
                stIspShpAttr.stManual.au16TextureStr[i] = texturestr; // 0-4096    (300) 无方向的细节纹理的锐化强度，
                stIspShpAttr.stManual.au16EdgeStr[i] = edgestr;       // 0-4096    (400) 带方向的边缘的锐化强度，
            }
            stIspShpAttr.stManual.u16TextureFreq = TextureFreq;       //细节纹理强度 0-4095 建议值 (128)
            stIspShpAttr.stManual.u16EdgeFreq = EdgeFreq;             //边缘锐化强度 0-4095 建议值 (96)
            stIspShpAttr.stManual.u8OverShoot = Overshoot;            //白点锐化强度 0-127  建议值 (100)
            stIspShpAttr.stManual.u8UnderShoot = UnderShoot;          //黑点锐化强度 0-127  建议值 (127)
            stIspShpAttr.stManual.u8ShootSupStr = supstr;             // 0-255  (8)图像锐化后的 overshoot 和 undershoot 的抑制强度
            stIspShpAttr.stManual.u8ShootSupAdj = supadj;             // 0-15   (9)图像锐化后的 overshoot 和 undershoot 的抑制强度的
                                                                      //调节。 该参数配合 ShootSupStr 使用， 用于调节ShootSupStr 作用的区域范围。该值越小，则越多的纹理区域的 shoot
                                                                      //会被 ShootSupStr 抑制； 该值越大，则只有很强的边缘的 shoot 会被 ShootSupStr 抑制， 纹理区域的 shoot 不会被抑制
            stIspShpAttr.stManual.u8DetailCtrl = detailctrl;          // 0-255  (128)
            stIspShpAttr.stManual.u8DetailCtrlThr = detailctrlthr;    // 0-255  (160)
            stIspShpAttr.stManual.u8EdgeFiltStr = edgefilt;           // 0-63   (53)
            stIspShpAttr.stManual.u8RGain = rgain;                    // 0-31   (28)
            stIspShpAttr.stManual.u8GGain = ggain;                    // 0-255  (32)
            stIspShpAttr.stManual.u8BGain = bgain;                    // 0-31   (28)
            stIspShpAttr.stManual.u8SkinGain = skingain;              // 0-31   (23)
            stIspShpAttr.stManual.u16MaxSharpGain = maxsharp;         // 0-2048 (160)
            break;
        }
        HI_MPI_ISP_SetIspSharpenAttr(ViPipe, &stIspShpAttr);
    }

//=======================================================================================================
// ISP  gamma校正
//=======================================================================================================
void mppIspGammaCtrl(HI_S32 ViPipe, HI_U8 disable, HI_U8 mode)
    {
        ISP_GAMMA_ATTR_S stGammaAttr;
        stGammaAttr.bEnable = !disable; // HI_FALSE： 关闭； HI_TRUE： 使能。默认值为 HI_TRUE。
        // stGammaAttr.u16Table = LUT;  //1024 段 LUT 表，用来表示输入输出值大小。取值范围： [0x0, 0xFFF]
        stGammaAttr.enCurveType = mode; // 0-lut,1-srgb,2-hdr,3-user,4butt; 仅在 Hi3559AV100 中支持  HDR
        HI_MPI_ISP_SetGammaAttr(ViPipe, &stGammaAttr);
    }

//=======================================================================================================
// ISP  CCM  色彩矫正 未使用
//=======================================================================================================
void mppIspCcmCtrl(HI_S32 ViPipe, HI_U8 mode, HI_U16 *pu16matrix)
    {
        ISP_COLORMATRIX_ATTR_S stCCMAttr;
        HI_MPI_ISP_GetCCMAttr(ViPipe, &stCCMAttr);
        switch (mode)
        {
        case 0:
            stCCMAttr.enOpType = OP_TYPE_AUTO;
            break;
        case 1:
            stCCMAttr.enOpType = OP_TYPE_MANUAL;
            stCCMAttr.stManual.bSatEn = HI_TRUE;
            memcpy(stCCMAttr.stManual.au16CCM, pu16matrix, CCM_MATRIX_SIZE);
            break;
        }
        HI_MPI_ISP_SetCCMAttr(ViPipe, &stCCMAttr);
    }

//=======================================================================================================
// ISP  CCM  色彩矫正 手动
//=======================================================================================================
void mppIspCCMCtrl(HI_S32 ViPipe, int mode1, int mode2, int saturation, int rr, int rg, int rb, int gr, int gg, int gb, int br, int bg, int bb)
    {
        ISP_SATURATION_ATTR_S stSatAttr;
        ISP_COLORMATRIX_ATTR_S stCCMAttr;

        stSatAttr.enOpType = mode1;
        stSatAttr.stManual.u8Saturation = saturation;     // 0-0xff,手动饱和度参数
        HI_MPI_ISP_SetSaturationAttr(ViPipe, &stSatAttr); //饱和度

        stCCMAttr.enOpType = mode2;         //
        stCCMAttr.stManual.bSatEn = 1;      //手动 CCM 模式下，用户可通过 bSatEn 参数选择饱和度是否生效。 bSatEn = 1，生效的CCM = Manual CCM * Saturation CCM，
                                            //用户可用该功能确定不同照度下的饱和度数 组； bSatEn = 0，生效的 CCM = Manual CCM。
        stCCMAttr.stManual.au16CCM[0] = rr; // 0 - 0xffff, 8bit小数精度。 bit15是符号位， 0 表示正数， 1 表示负数，例如 0x8010 表示-16。
        stCCMAttr.stManual.au16CCM[1] = rg;
        stCCMAttr.stManual.au16CCM[2] = rb;
        stCCMAttr.stManual.au16CCM[3] = gr;
        stCCMAttr.stManual.au16CCM[4] = gg;
        stCCMAttr.stManual.au16CCM[5] = gb;
        stCCMAttr.stManual.au16CCM[6] = br;
        stCCMAttr.stManual.au16CCM[7] = bg;
        stCCMAttr.stManual.au16CCM[8] = bb;
        HI_MPI_ISP_SetCCMAttr(ViPipe, &stCCMAttr);
    }

/*================================================================================================
    Crosstalk Removal 模块的主要功能是为了平衡 rawdata 之间临近像素 Gr 和 Gb 之间的差异， 能够有效防止 demosaic
    插值算法产生的方格或其他类似 pattern。 由于 sensor 可能会因为特殊角度的光线入射而产生Crosstalk，形成一些 pattern，
    根本原因就是因为临近像素值之间 Gr 和 Gb 值域不一致
================================================================================================*/
void mppIspCrosstalkCtrl(HI_S32 ViPipe, HI_U8 mode, HI_U8 thr, HI_U8 tar)
    {
    }

/*=================================================================================================
     HLC（High Light Cover）高光遮蔽模块，是用于将图像中亮度最高的区域（一般都是
    夜晚场景的车灯或者路灯等光源） 拉灰，以减少类似于车灯等高亮光源对人眼的刺激
 =================================================================================================*/
    // ISP   HLC。暂时没有使用
void mppIspHlcCtrl(HI_S32 ViPipe, HI_U8 mode, HI_U8 thr, HI_U8 tar)
    {
        ISP_HLC_ATTR_S stIspHlcAttr;
        stIspHlcAttr.bEnable = mode;
        stIspHlcAttr.u8LumaThr = thr;
        stIspHlcAttr.u8LumaTarget = tar;
        HI_MPI_ISP_SetIspHlcAttr(ViPipe, &stIspHlcAttr);
    }

//================================================================================================
// DE 改善噪声形态， 使得噪声均匀细碎， 同时改善边缘毛糙。
//================================================================================================
void mppIspDeCtrl(HI_S32 ViPipe, int enable, int mode, HI_U8 GlobaGain, HI_U8 GainLF, HI_U8 GainHF)
    {

        ISP_DE_ATTR_S stIspDeAttr;
        HI_MPI_ISP_GetDEAttr(ViPipe, &stIspDeAttr); // Get
        if (enable)
            stIspDeAttr.bEnable = HI_TRUE; // HI_FALSE=关闭，HI_TRUE=使能
        else
            stIspDeAttr.bEnable = HI_FALSE; // HI_FALSE=关闭，HI_TRUE=使能

        switch (mode)
        {
        case 0: // auto
            stIspDeAttr.enOpType = OP_TYPE_AUTO;
            break;

        case 1: // manual
            stIspDeAttr.enOpType = OP_TYPE_MANUAL;
            stIspDeAttr.stManual.u16GlobalGain = GlobaGain; // DE 全局叠加强度增益,范围[0,256]  默认=150
            stIspDeAttr.stManual.u16GainLF = GainLF;        // DE 低频叠加强度增益 范围[0,32]   默认=9
            stIspDeAttr.stManual.u16GainHF = GainHF;        // DE 高频叠加强度增益 范围[0,32]   默认=9
            break;
        }

        HI_MPI_ISP_SetDEAttr(ViPipe, &stIspDeAttr); // Set
    }

/*=======================================================================================================
 *  LDCI 是局域自动对比度增强的简称（Local Dynamic Contrast Improvement）。该算法采
    用局域直方图均衡来增强图像局部对比度， 提升暗区细节
    enable = 1 使能，enable = 0 关闭
    mode   = 1 Manual     mode = 0 Auto
* =====================================================================================================*/
void mppIspLdciCtrl(HI_S32 ViPipe, int enable, int mode, int LPFSigma, int Blc, int pos_mean, int pos_sigma, int pos_wgt,
                        int neg_mean, int neg_sigma, int neg_wgt)
    {
        ISP_LDCI_ATTR_S stLDCIAttr;
        HI_MPI_ISP_GetLDCIAttr(ViPipe, &stLDCIAttr);
        if (enable)
            stLDCIAttr.bEnable = HI_TRUE;
        else
            stLDCIAttr.bEnable = HI_FALSE;
        if (mode)
            stLDCIAttr.enOpType = OP_TYPE_MANUAL; // OP_TYPE_AUTO： 自动；OP_TYPE_MANUAL： 手动。默认值为自动
        else
            stLDCIAttr.enOpType = OP_TYPE_AUTO;
        stLDCIAttr.u8GaussLPFSigma = LPFSigma; // LPF滤波强度 其值越小说明 LDCI 作用越局域, 取值范围[0x01,0xFF]
        stLDCIAttr.stManual.u16BlcCtrl = Blc;  //手动模式下暗区增益控制强度用于抑制暗区噪声，取值范围[0x01,0x1FF]

        //直方图均衡结果与原图融合权重曲线，可根据原图亮度控制 *提亮程度*；曲线呈高斯分布，横坐标为亮度。
        stLDCIAttr.stManual.stHeWgt.stHePosWgt.u8Mean = pos_mean;   // Gauss 分布曲线数学期望,取值范围： [0x0, 0xFF]。
        stLDCIAttr.stManual.stHeWgt.stHePosWgt.u8Sigma = pos_sigma; // Gauss 分布曲线标准差， 取值范围： [0x1, 0xFF]。
        stLDCIAttr.stManual.stHeWgt.stHePosWgt.u8Wgt = pos_wgt;     // Gauss 分布曲线权重,取值范围： [0x0, 0xFF]
        
        //直方图均衡结果与原图融合权重曲线，可根据原图亮度控制 *减暗程度*；曲线呈高斯分布，横坐标为亮度
        stLDCIAttr.stManual.stHeWgt.stHeNegWgt.u8Mean = neg_mean;
        stLDCIAttr.stManual.stHeWgt.stHeNegWgt.u8Sigma = neg_sigma;
        stLDCIAttr.stManual.stHeWgt.stHeNegWgt.u8Wgt = neg_wgt;

        HI_MPI_ISP_SetLDCIAttr(ViPipe, &stLDCIAttr);
    }

/*===================================================================================================
     * 噪模块在 Bayer 域进行空域处理， 分别对亮度噪声和色度噪声做去噪处理， 且四个通道强度分别可调， 具有保留边缘和
     * 纹理的优点， 并对随机噪声有一定的保留，提高整体图像信噪比
===================================================================================================*/
// byer NR
void mppIspNrCtrl(HI_S32 ViPipe, int enable, int mode, int chroma, int fine, int coring, int coar)
    {
        ISP_NR_ATTR_S stNrAttr;
        HI_MPI_ISP_GetNRAttr(ViPipe, &stNrAttr);
        if (enable)
            stNrAttr.bEnable = HI_TRUE;
        else
            stNrAttr.bEnable = HI_FALSE;
        if (mode)
        {
            stNrAttr.enOpType = OP_TYPE_MANUAL;

            stNrAttr.stManual.au8ChromaStr[0] = chroma; //值越大去色噪越大
            stNrAttr.stManual.au8ChromaStr[1] = chroma;
            stNrAttr.stManual.au8ChromaStr[2] = chroma;
            stNrAttr.stManual.au8ChromaStr[3] = chroma;
            stNrAttr.stManual.u8FineStr = fine;        //值越大亮噪去除强度越大
            stNrAttr.stManual.u16CoringWgt = coring;   //值越大保留随机噪声越多
            stNrAttr.stManual.au16CoarseStr[0] = coar; //值越大亮噪声去除越大
            stNrAttr.stManual.au16CoarseStr[1] = coar;
            stNrAttr.stManual.au16CoarseStr[2] = coar;
            stNrAttr.stManual.au16CoarseStr[3] = coar;
        }
        else
            stNrAttr.enOpType = OP_TYPE_AUTO;
        HI_MPI_ISP_SetNRAttr(ViPipe, &stNrAttr);
    }
//=======================================================================================================
// ISP   3DNR降噪控制。 函数有问题           暂时没有使用
//=======================================================================================================
#if 0
void mppIsp3DNRCtrl(HI_S32 ViPipe, int ies, int iedz)
    {
        VPSS_GRP_NRX_PARAM_S stNRXParam;
        HI_MPI_VPSS_GetGrpNRXParam(ViPipe, &stNRXParam);
        stNRXParam.enNRVer = VPSS_NR_V2;
        stNRXParam.stNRXParam_V2.enOptMode = OPERATION_MODE_AUTO;

        //边缘增强 //0-255
        stNRXParam.stNRXParam_V2.stNRXAuto.pastNRXParam->IEy[0].IES0 = ies;
        stNRXParam.stNRXParam_V2.stNRXAuto.pastNRXParam->IEy[0].IES1 = ies;
        stNRXParam.stNRXParam_V2.stNRXAuto.pastNRXParam->IEy[0].IES3 = ies;
        stNRXParam.stNRXParam_V2.stNRXAuto.pastNRXParam->IEy[0].IEDZ = ies;
        
        //噪声控制 //0-999
        stNRXParam.stNRXParam_V2.stNRXAuto.pastNRXParam->IEy[0].IEDZ = iedz;
        stNRXParam.stNRXParam_V2.stNRXAuto.pastNRXParam->IEy[1].IES0 = ies;
        stNRXParam.stNRXParam_V2.stNRXAuto.pastNRXParam->IEy[1].IES1 = ies;
        stNRXParam.stNRXParam_V2.stNRXAuto.pastNRXParam->IEy[1].IES3 = ies;
        stNRXParam.stNRXParam_V2.stNRXAuto.pastNRXParam->IEy[1].IEDZ = ies;
        stNRXParam.stNRXParam_V2.stNRXAuto.pastNRXParam->IEy[1].IEDZ = iedz;
        stNRXParam.stNRXParam_V2.stNRXAuto.pastNRXParam->IEy[2].IES0 = ies;
        stNRXParam.stNRXParam_V2.stNRXAuto.pastNRXParam->IEy[2].IES1 = ies;
        stNRXParam.stNRXParam_V2.stNRXAuto.pastNRXParam->IEy[2].IES3 = ies;
        stNRXParam.stNRXParam_V2.stNRXAuto.pastNRXParam->IEy[2].IEDZ = ies;
        stNRXParam.stNRXParam_V2.stNRXAuto.pastNRXParam->IEy[2].IEDZ = iedz;

        HI_MPI_VPSS_SetGrpNRXParam(ViPipe, &stNRXParam);
        /*
            stNRXParam.stNRXParam_V2.stNRXAuto.pau32ISO;
            //边缘增强
            stNRXParam.stNRXParam_V2.stNRXManual .stNRXParam.IEy[0].IES0 = ies0;//0-255
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.IEy[0].IES1 = ies1;//0-255
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.IEy[0].IES2 = ies2;//0-255
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.IEy[0].IES3 = ies3;//0-255
            //噪声控制
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.IEy[0].IEDZ = iedz;//0-999

            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.IEy[1].IES0 = ies0;//0-255
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.IEy[1].IES1 = ies1;//0-255
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.IEy[1].IES2 = ies2;//0-255
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.IEy[1].IES3 = ies3;//0-255
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.IEy[1].IEDZ = iedz;//0-999
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.IEy[2].IES0 = ies0;//0-255
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.IEy[2].IES1 = ies1;//0-255
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.IEy[2].IES2 = ies2;//0-255
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.IEy[2].IES3 = ies3;//0-255
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.IEy[2].IEDZ = iedz;//0-999

            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.SFy[0] = sfy;
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.SFy[1] = sfy;
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.SFy[2] = sfy;
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.MDy[0] = mdy;
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.MDy[1] = mdy;
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.RFs = rfs;
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.TFy[0] = tfy;
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.TFy[1] = tfy;
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.pNRc = pnrc;
            stNRXParam.stNRXParam_V2.stNRXManual.stNRXParam.NRc = nrc;
            HI_MPI_VPSS_SetGrpNRXParam(ViPipe, &stNRXParam);
        */
    }
#endif
//=======================================================================================================
// MWB校准 ,  手动白平衡
//=======================================================================================================
#define DIV_0_TO_1(a) ((0 == (a)) ? 100 : (a))
HI_U32 mppAwbCalibration(HI_S32 ViPipe,HI_U32 u32Mode,ISP_AWB_Calibration_Gain_S *pstAWBCalibGain)
{
    ISP_EXP_INFO_S stExpInfo;
    ISP_EXPOSURE_ATTR_S stExpAttr;
    HI_U16 u16GoldenRgain = 0;
    HI_U16 u16GoldenBgain = 0;
    HI_S16 s16Alpha = 0;
    HI_S16 total_count = 0;
    HI_S16 stable_count = 0;
    
    int return_value = 1;

    MWB_State =1;

    HI_MPI_ISP_GetExposureAttr(ViPipe, &stExpAttr);
    stExpAttr.enOpType = OP_TYPE_AUTO;                          //改为自动曝光 EDWIN2022-09-22

    //设置防闪烁使能，频率值为50Hz
    stExpAttr.stAuto.stAntiflicker.bEnable = HI_TRUE;
    stExpAttr.stAuto.stAntiflicker.u8Frequency = 50;
    HI_MPI_ISP_SetExposureAttr(ViPipe, &stExpAttr);


    while ((stable_count < 5) && (total_count < 20))
    {
        HI_MPI_ISP_QueryExposureInfo(ViPipe, &stExpInfo);//获取 AE 内部状态信息

        usleep(10000000 / DIV_0_TO_1(stExpInfo.u32Fps));

        if (stExpInfo.s16HistError > stExpAttr.stAuto.u8Tolerance) //自动曝光调整时对画面亮度的容忍偏差。取值范围： [0x0, 0xFF]，默认值为 0x2。
        {
            stable_count = 0;
        }
        else
        {
            stable_count ++;
        }
        total_count ++;
        printf("MWB INFO:: total_count=%d,stable_count=%d\n",total_count,stable_count);
    }
    if (stable_count >= 5)
    {
        HI_MPI_ISP_GetLightboxGain(ViPipe, pstAWBCalibGain);
        if (1 == u32Mode)
        {
            pstAWBCalibGain->u16AvgRgain =  (HI_U16)((HI_S16)(pstAWBCalibGain->u16AvgRgain)  + ((((HI_S16)u16GoldenRgain - (HI_S16)(pstAWBCalibGain->u16AvgRgain))* s16Alpha) >> 10));
            pstAWBCalibGain->u16AvgBgain = (HI_U16)((HI_S16)(pstAWBCalibGain->u16AvgBgain) + ((((HI_S16)u16GoldenBgain  - (HI_S16)(pstAWBCalibGain->u16AvgBgain))* s16Alpha) >> 10 ));
        }
        //printf("MWB INFO:: \tu16AvgRgain =%8d, u16AvgBgain = %8d\n", stAWBCalibGain.u16AvgRgain, stAWBCalibGain.u16AvgBgain);
        printf("MWB INFO:: \tu16AvgRgain =%8d, u16AvgBgain = %8d\n", pstAWBCalibGain->u16AvgRgain-20, pstAWBCalibGain->u16AvgBgain);
        return_value = 0;
        MWB_State = 0;
        return HI_SUCCESS;
    }
    else
    {
        printf("MWB INFO:: AE IS NOT STABLE,PLEASE WAIT\n");
        return_value = 1;
        MWB_State = 0;
        return HI_FAILURE;
    }

    //========================================================================================
    // add by edwin 2022-09-22

    int ae_mode         = GetIniKeyInt("isp",   "ae_mode",          PARAM_FILE);
    int connect_device  = GetIniKeyInt("Option","connect_device",   PARAM_FILE);    //1=OV6946,2=OS01A
    HI_MPI_ISP_GetExposureAttr(ViPipe, &stExpAttr);

    if(connect_device==1)                           //Bypass
    {
        stExpAttr.bByPass = HI_TRUE;
    }
    else if(connect_device == 2)                    //mipi AUTO
    {
        stExpAttr.enOpType = OP_TYPE_AUTO;
    }
    HI_MPI_ISP_SetExposureAttr(ViPipe, &stExpAttr);
    //==========================================================================================
    MWB_State = 0;

    return return_value;
}





//=======================================================================================================
// VI初始化。            暂时没有使用
//=======================================================================================================
HI_S32 configViInit(HI_U32 u32ViIntfType)
    {
        SIZE_S stSize;
        stViConfig.s32WorkingViNum = 1;
        stViConfig.as32WorkingViId[0] = 0;
        stViConfig.astViInfo[0].stSnsInfo.enSnsType = u32ViIntfType; // 1=OV426  0=OS01A
        stViConfig.astViInfo[0].stSnsInfo.s32SnsId = u32ViIntfType;  // 1=OV426  0=OS01A
        stViConfig.astViInfo[0].stSnsInfo.s32BusId = 0;
        stViConfig.astViInfo[0].stSnsInfo.MipiDev = u32ViIntfType; // 1=OV426  0=OS01A
        stViConfig.astViInfo[0].stDevInfo.ViDev = u32ViIntfType;   // 1=OV426  0=OS01A
        stViConfig.astViInfo[0].stDevInfo.enWDRMode = WDR_MODE_NONE;
        stViConfig.astViInfo[0].stPipeInfo.aPipe[0] = 0;
        stViConfig.astViInfo[0].stPipeInfo.aPipe[1] = -1;
        stViConfig.astViInfo[0].stPipeInfo.aPipe[2] = -1;
        stViConfig.astViInfo[0].stPipeInfo.aPipe[3] = -1;
        stViConfig.astViInfo[0].stPipeInfo.enMastPipeMode = VI_ONLINE_VPSS_OFFLINE;
        stViConfig.astViInfo[0].stPipeInfo.bMultiPipe = HI_FALSE;
        stViConfig.astViInfo[0].stPipeInfo.bVcNumCfged = HI_FALSE;
        stViConfig.astViInfo[0].stChnInfo.ViChn = 0;
        stViConfig.astViInfo[0].stChnInfo.enPixFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
        stViConfig.astViInfo[0].stChnInfo.enDynamicRange = DYNAMIC_RANGE_SDR8;
        stViConfig.astViInfo[0].stChnInfo.enVideoFormat = VIDEO_FORMAT_LINEAR;
        stViConfig.astViInfo[0].stChnInfo.enCompressMode = COMPRESS_MODE_NONE;
        hi_memset(&stViConfig.astViInfo[0].stSnapInfo, sizeof(SAMPLE_SNAP_INFO_S), 0, sizeof(SAMPLE_SNAP_INFO_S));
        // get picture size
        switch (stViConfig.astViInfo[0].stSnsInfo.enSnsType)
        {
        case OV426:
            stSize.u32Width = 400;
            stSize.u32Height = 400;
            break;
        case OS01A:
            stSize.u32Width = 800;
            stSize.u32Height = 800;
            break;
        case OV9734:
            stSize.u32Width = 720;
            stSize.u32Height = 720;
            break;
        default:
            stSize.u32Width = 400;
            stSize.u32Height = 400;
            break;
        }
        if (stSize.u32Width > SCREEN_WIDTH) //          edwin 2022-07-22
                                            // if(stSize.u32Width > 500) //不是OV6946         edwin 2022-07-22
            VpssChn = 1;
        else
            VpssChn = 0;
        printf("VPSS INFO:: configViInit_VpssChn = %d \n", VpssChn);
        return 0;
    }

//=======================================================================================================
// VO初始化            暂时没有使用
//=======================================================================================================
HI_S32 configVoInit(HI_U32 u32VoIntfType)
    {
        RECT_S stDefDispRect = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
        SIZE_S stDefImageSize = {SCREEN_WIDTH, SCREEN_HEIGHT};
        stVoConfig.VoDev = SAMPLE_VO_DEV_UHD;
        stVoConfig.enPicSize = PIC_800x800;
        stVoConfig.u32BgColor = COLOR_RGB_BLACK;
        stVoConfig.enPixFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
        stVoConfig.stDispRect = stDefDispRect;
        stVoConfig.stImageSize = stDefImageSize;
        stVoConfig.enVoPartMode = VO_PART_MODE_SINGLE;
        stVoConfig.u32DisBufLen = 3;
        stVoConfig.enDstDynamicRange = DYNAMIC_RANGE_SDR8;
        stVoConfig.enVoMode = VO_MODE_1MUX;
        switch (u32VoIntfType)
        {
        case 0:
            stVoConfig.enVoIntfType = VO_INTF_HDMI;
            stVoConfig.enIntfSync = VO_OUTPUT_1080P60;
            break;
        case 1:
            stVoConfig.enVoIntfType = VO_INTF_MIPI;
            stVoConfig.enIntfSync = VO_OUTPUT_USER;
            g_mipi_tx_config = &MIPI_TX_10INCH_1280x800_60_CONFIG_VIDEO;
            g_mipi_tx_sync_info = &MIPI_TX_10INCH_1280x800_60_SYNC_INFO;
            g_mipi_tx_user_intfsync_info = &MIPI_TX_10INCH_1280x800_60_USER_INTFSYNC_INFO;
            g_mipi_tx_lcd_resolution = &MIPI_TX_10INCH_1280x800_60_LCD_RESOLUTION;
            g_mipi_lcd_init = &InitScreen_mipi_10inch_1280x800;
            break;
        case 2:
            stVoConfig.enVoIntfType = VO_INTF_MIPI;
            stVoConfig.enIntfSync = VO_OUTPUT_USER;
            g_mipi_tx_config = &MIPI_TX_10INCH_1280x800_60_CONFIG_VIDEO;
            g_mipi_tx_sync_info = &MIPI_TX_10INCH_1280x800_60_SYNC_INFO;
            g_mipi_tx_user_intfsync_info = &MIPI_TX_10INCH_1280x800_60_USER_INTFSYNC_INFO;
            g_mipi_tx_lcd_resolution = &MIPI_TX_10INCH_1280x800_60_LCD_RESOLUTION;
            g_mipi_lcd_init = &InitScreen_mipi_10inch_1280x800;
            break;
        }
        return HI_SUCCESS;
    }

//=======================================================================================================
// 配置 VI--VO， 实际在项目中使用的此函数进行配置 ------------------------------------- [main.c step 2.1.0]
//=======================================================================================================
HI_S32 configInit(HI_U32 u32ViIntfType, HI_U32 u32VoIntfType)
    {
        SIZE_S stSize;
        RECT_S stDefDispRect = {0, 0, 400, 400}; //
        SIZE_S stDefImageSize = {800, 800};      //{SCREEN_WIDTH, SCREEN_HEIGHT};//xwc

        // config  VI
        stViConfig.s32WorkingViNum = 1;
        stViConfig.as32WorkingViId[0] = 0;
        stViConfig.astViInfo[0].stSnsInfo.enSnsType         = u32ViIntfType; // OV426=1, OS01A=0
        stViConfig.astViInfo[0].stSnsInfo.s32SnsId          = u32ViIntfType;
        stViConfig.astViInfo[0].stSnsInfo.s32BusId          = 0;
        stViConfig.astViInfo[0].stSnsInfo.MipiDev           = u32ViIntfType; // OV426=1, OS01A=0
        stViConfig.astViInfo[0].stDevInfo.ViDev             = u32ViIntfType; // OV426=1
        stViConfig.astViInfo[0].stDevInfo.enWDRMode         = WDR_MODE_NONE;
        stViConfig.astViInfo[0].stPipeInfo.aPipe[0]         = 0;
        stViConfig.astViInfo[0].stPipeInfo.aPipe[1]         = -1; // 1; wdr
        stViConfig.astViInfo[0].stPipeInfo.aPipe[2]         = -1;
        stViConfig.astViInfo[0].stPipeInfo.aPipe[3]         = -1;
        stViConfig.astViInfo[0].stPipeInfo.enMastPipeMode   = VI_ONLINE_VPSS_OFFLINE;
        stViConfig.astViInfo[0].stPipeInfo.bMultiPipe       = HI_FALSE;
        stViConfig.astViInfo[0].stPipeInfo.bVcNumCfged      = HI_FALSE;
        stViConfig.astViInfo[0].stChnInfo.ViChn             = 0;
        stViConfig.astViInfo[0].stChnInfo.enPixFormat       = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
        stViConfig.astViInfo[0].stChnInfo.enDynamicRange    = DYNAMIC_RANGE_SDR8;
        stViConfig.astViInfo[0].stChnInfo.enVideoFormat     = VIDEO_FORMAT_LINEAR;
        stViConfig.astViInfo[0].stChnInfo.enCompressMode    = COMPRESS_MODE_NONE;

        hi_memset(&stViConfig.astViInfo[0].stSnapInfo, sizeof(SAMPLE_SNAP_INFO_S), 0, sizeof(SAMPLE_SNAP_INFO_S));

        // get picture size
        switch (stViConfig.astViInfo[0].stSnsInfo.enSnsType)
        {
        case OV426:
            stSize.u32Width  = 400;
            stSize.u32Height = 400;
            break;
        case OS01A:
            stSize.u32Width  = 800;
            stSize.u32Height = 800;
            break;
        case OV9734:
            stSize.u32Width  = 720;
            stSize.u32Height = 720;
            break;
        default:
            stSize.u32Width  = 400;
            stSize.u32Height = 400;
            break;
        }

        // if(stSize.u32Width>SCREEN_WIDTH)  //          edwin 2022-07-22
        if (stSize.u32Width > 800) //不是OV6946         edwin 2022-07-22
            VpssChn = 1;
        else
            VpssChn = 0;
        printf("VPSS INFO:: configInit_VpssChn = %d \n", VpssChn);

        // config VO
        stVoConfig.VoDev                = SAMPLE_VO_DEV_UHD;
        stVoConfig.enPicSize            = PIC_800x800;
        stVoConfig.u32BgColor           = COLOR_RGB_BLACK;
        stVoConfig.enPixFormat          = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
        stVoConfig.stDispRect           = stDefDispRect;
        stVoConfig.enVoPartMode         = VO_PART_MODE_SINGLE;
        stVoConfig.u32DisBufLen         = 3;
        stVoConfig.enDstDynamicRange    = DYNAMIC_RANGE_SDR8;
        stVoConfig.enVoMode             = VO_MODE_1MUX;

        // stVoConfig.stImageSize       = stDefImageSize;
        switch (u32VoIntfType)
        {
        case 1:
            stVoConfig.stImageSize.u32Width  = 400;
            stVoConfig.stImageSize.u32Height = 400;
            break;
        case 2:
            stVoConfig.stImageSize.u32Width  = 600;
            stVoConfig.stImageSize.u32Height = 600;
            break;
        case 3:
            stVoConfig.stImageSize.u32Width  = 800;
            stVoConfig.stImageSize.u32Height = 800;
            break;
        case 4:
            stVoConfig.stImageSize.u32Width  = 1000;
            stVoConfig.stImageSize.u32Height = 1000;
            break;
        }

        //HDMI输出类型
        stVoConfig.enVoIntfType = VO_INTF_HDMI;
        switch(hdmi_disp_mode)
        {
            case HDMI_1080P:
                stVoConfig.enIntfSync = VO_OUTPUT_1080P60;
                break;
            case HDMI_1920x1200:
                stVoConfig.enIntfSync = VO_OUTPUT_1920x1200_60;
                break;
        }
        return HI_SUCCESS;
    }

//=======================================================================================================
//系统初始化   ---本文夹下的main.c文件内调用，进行系统初始化--------------------------------- [main.c step 2.2.0]
//=======================================================================================================
HI_S32 sysInit()
    {
        VB_CONFIG_S stVbConf;
        HI_U32 u32BlkSize;
        // config vb
        hi_memset(&stVbConf, sizeof(VB_CONFIG_S), 0, sizeof(VB_CONFIG_S));
        stVbConf.u32MaxPoolCnt = 2;
        u32BlkSize = COMMON_GetPicBufferSize(1920, 1080, SAMPLE_PIXEL_FORMAT, DATA_BITWIDTH_8, COMPRESS_MODE_SEG, DEFAULT_ALIGN);
        stVbConf.astCommPool[0].u64BlkSize = u32BlkSize;
        stVbConf.astCommPool[0].u32BlkCnt = 10;
        u32BlkSize = VI_GetRawBufferSize(1920, 1080, PIXEL_FORMAT_RGB_BAYER_10BPP, COMPRESS_MODE_LINE, DEFAULT_ALIGN);
        stVbConf.astCommPool[1].u64BlkSize = u32BlkSize;
        stVbConf.astCommPool[1].u32BlkCnt = 15;
        HI_MPI_SYS_Exit();
        HI_MPI_VB_Exit();
        CHECK_RET(HI_MPI_VB_SetConfig(&stVbConf), "HI_MPI_VB_SetConfig()");
        CHECK_RET(HI_MPI_VB_Init(), "HI_MPI_VB_Init()");
        CHECK_RET(HI_MPI_SYS_Init(), "HI_MPI_SYS_Init()");
        return HI_SUCCESS;
    }



//=======================================================================================================
// new
//=======================================================================================================
int mppFrameResize(int disWidth, int disHeight) // disWidth=400/800  disHeight=400/800
{
    int x, y, width, height;
    VI_CROP_INFO_S stCropInfo;
    if (stViConfig.astViInfo[0].stSnsInfo.enSnsType) // DVP OV6946
    {
        if (disWidth > disHeight)
        {
            x = 0;
            y = CAMER_HEIGHT * (disWidth - disHeight) / (disHeight * 2);
            width = CAMER_WIDTH;
            height = CAMER_HEIGHT - CAMER_HEIGHT * (disWidth - disHeight) / disHeight;
        }
        else
        {
            x = CAMER_WIDTH * (disHeight - disWidth) / (disWidth * 2);
            y = 0;
            width = CAMER_WIDTH - CAMER_WIDTH * (disHeight - disWidth) / disWidth;
            height = CAMER_HEIGHT;
        }
    }
    else // MIPI OS01A
    {
        if (disWidth > disHeight)
        {
            x = 0;
            y = 800 * (disWidth - disHeight) / (disHeight * 2);
            width = 800;
            height = 800 - 800 * (disWidth - disHeight) / disHeight;
        }
        else
        {
            //x = 800 * (1280 - disWidth) / (disWidth * 2);
			x = 0;
            y = 0;
            width = 800 - 800 * (disHeight - disWidth) / disWidth;
            height = 800;
        }
    }
    stCropInfo.bEnable = HI_TRUE;
    stCropInfo.enCropCoordinate = VI_CROP_ABS_COOR; //起点坐标模式 => 绝对坐标模式
    stCropInfo.stCropRect.s32X = x;
    stCropInfo.stCropRect.s32Y = y;
    stCropInfo.stCropRect.u32Width = width;
    stCropInfo.stCropRect.u32Height = height;
    printf("Image_CUT::x:%d,y:%d,width:%d,hegiht:%d\n", x, y, width, height);
    HI_MPI_VI_SetChnCrop(0, 0, &stCropInfo);
    int mode;
    mode = read_osd_parameter_key("Option", "Rotate", 2);
    printf("rotate = %d\n", mode);
    mppFrameRotate(mode);
    return HI_SUCCESS;
}

//=======================================================================================================
// ******VPSS初始化******          本文夹下的main.c文件内调用--------------------- [main.c step 2.4.0]
//=======================================================================================================
HI_S32 viVpssInit(SAMPLE_VI_CONFIG_S stViConfig, int disWidth, int disHeight)
{
    VPSS_GRP_ATTR_S stVpssGrpAttr;                  //定义 VPSS GROUP 属性
    VPSS_CHN_ATTR_S stVpssChnAttr;                  //定义 VPSS 物理通道属性。
    MPP_CHN_S stSrcChn;
    MPP_CHN_S stDestChn;
    if (stViConfig.astViInfo[0].stSnsInfo.s32SnsId)
        mppFrameResize(400, 400);
    else
        mppFrameResize(800, 800);
    // config vi - vpss
    hi_memset(&stVpssGrpAttr, sizeof(VPSS_GRP_ATTR_S), 0, sizeof(VPSS_GRP_ATTR_S));

    //定义 VPSS GROUP 属性
    stVpssGrpAttr.stFrameRate.s32SrcFrameRate   = -1;
    stVpssGrpAttr.stFrameRate.s32DstFrameRate   = -1;
    stVpssGrpAttr.enDynamicRange                = DYNAMIC_RANGE_SDR8;
    stVpssGrpAttr.enPixelFormat                 = stViConfig.astViInfo[0].stChnInfo.enPixFormat;
    stVpssGrpAttr.u32MaxW                       = 1920;
    stVpssGrpAttr.u32MaxH                       = 1080;
    stVpssGrpAttr.bNrEn                         = HI_TRUE;
    stVpssGrpAttr.stNrAttr.enCompressMode       = COMPRESS_MODE_FRAME;
    stVpssGrpAttr.stNrAttr.enNrMotionMode       = NR_MOTION_MODE_NORMAL;

    //定义 VPSS 物理通道属性。
    stVpssChnAttr.u32Width                      = disWidth;
    stVpssChnAttr.u32Height                     = disHeight;
    stVpssChnAttr.enChnMode                     = VPSS_CHN_MODE_USER;
    stVpssChnAttr.enCompressMode                = stViConfig.astViInfo[0].stChnInfo.enCompressMode;
    stVpssChnAttr.enDynamicRange                = stViConfig.astViInfo[0].stChnInfo.enDynamicRange;
    stVpssChnAttr.enVideoFormat                 = stViConfig.astViInfo[0].stChnInfo.enVideoFormat;
    stVpssChnAttr.enPixelFormat                 = stViConfig.astViInfo[0].stChnInfo.enPixFormat;
    stVpssChnAttr.stFrameRate.s32SrcFrameRate   = -1;
    stVpssChnAttr.stFrameRate.s32DstFrameRate   = -1;
    stVpssChnAttr.u32Depth                      = 0;
    stVpssChnAttr.bMirror                       = HI_FALSE;                 //左右镜像
    stVpssChnAttr.bFlip                         = HI_FALSE;                 //上下反转
    stVpssChnAttr.stAspectRatio.enMode          = ASPECT_RATIO_NONE;        //旋转
    stSrcChn.enModId                            = HI_ID_VI;
    stSrcChn.s32DevId                           = 0;
    stSrcChn.s32ChnId                           = 0;
    stDestChn.enModId                           = HI_ID_VPSS;
    stDestChn.s32DevId                          = 0;
    stDestChn.s32ChnId                          = VpssChn;
    CHECK_RET(HI_MPI_VPSS_CreateGrp(0, &stVpssGrpAttr), "HI_MPI_VPSS_CreateGrp(0)");
    CHECK_RET(HI_MPI_VPSS_SetChnAttr(0, VpssChn, &stVpssChnAttr), "HI_MPI_VPSS_SetChnAttr(0,0)");
    CHECK_RET(HI_MPI_VPSS_EnableChn(0, VpssChn), "HI_MPI_VPSS_EnableChn(0,0)");
    CHECK_RET(HI_MPI_VPSS_SetChnRotation(0, VpssChn, ROTATION_180), "HI_MPI_VPSS_SetChnRotate(0,vpssChn, ROTATE_180)");
    CHECK_RET(HI_MPI_VPSS_StartGrp(0), "HI_MPI_VPSS_StartGrp(0)");
    CHECK_RET(HI_MPI_SYS_Bind(&stSrcChn, &stDestChn), "HI_MPI_SYS_Bind(VI-VPSS)");
    return HI_SUCCESS;
}

//=======================================================================================================
//消毁 VI  VPSS
//=======================================================================================================
HI_S32 viVpssDeinit()
{
    MPP_CHN_S stSrcChn;
    MPP_CHN_S stDestChn;
    stSrcChn.enModId = HI_ID_VI;
    stSrcChn.s32DevId = 0;
    stSrcChn.s32ChnId = 0;
    stDestChn.enModId = HI_ID_VPSS;
    stDestChn.s32DevId = 0;
    stDestChn.s32ChnId = VpssChn;
    CHECK_RET(HI_MPI_SYS_UnBind(&stSrcChn, &stDestChn), "HI_MPI_SYS_UnBind(VI-VPSS)");
    CHECK_RET(HI_MPI_VPSS_DisableChn(0, VpssChn), "HI_MPI_VPSS_DisableChn(0,0)");
    CHECK_RET(HI_MPI_VPSS_StopGrp(0), "HI_MPI_VPSS_StopGrp(0)");
    CHECK_RET(HI_MPI_VPSS_DestroyGrp(0), "HI_MPI_VPSS_DestroyGrp(0)");
    return HI_SUCCESS;
}

//===================================================================================================================================
// DVP isp ctrl
//===================================================================================================================================
void mppisp_dvp_ctrl()
{
    HI_U16 tmp_ccmmatrix[9];
    tmp_ccmmatrix[0] = 0x01F1; // settings.value("isp/ccm_rr").toInt();             //465
    tmp_ccmmatrix[1] = 0x80E1; // settings.value("isp/ccm_rg").toInt();             //32984
    tmp_ccmmatrix[2] = 0x8010; // settings.value("isp/ccm_rb").toInt();             //32775
    tmp_ccmmatrix[3] = 0x8076; // settings.value("isp/ccm_gr").toInt();             //32832
    tmp_ccmmatrix[4] = 0x01B8; // settings.value("isp/ccm_gg").toInt();             //449
    tmp_ccmmatrix[5] = 0x8042; // settings.value("isp/ccm_gb").toInt();             //32897
    tmp_ccmmatrix[6] = 0x803D; // settings.value("isp/ccm_br").toInt();             //1
    tmp_ccmmatrix[7] = 0x8146; // settings.value("isp/ccm_bg").toInt();             //32959
    tmp_ccmmatrix[8] = 0x0283; // settings.value("isp/ccm_bb").toInt();             //446
    mppIspAEDisable();
    mppIspAwb(0, 2, 5500, 280, 260, 260, 350);
    mppIspSharpen(0, 1, 1000, 2000, 20, 30, 225, 16, 225, 16, 100, 700, 700, 200, 12, 200, 200, 50, 20, 20, 20, 20, 200);
    mppIspGammaCtrl(0, 0, 1);
    mppIspCcmCtrl(0, 1, tmp_ccmmatrix);
}

//===================================================================================================================================
// MIPI isp ctrl
//===================================================================================================================================
void mppisp_mipi_ctrl()
{
    HI_U16 tmp_ccmmatrix[9];
    tmp_ccmmatrix[0] = 0x01F1; // settings.value("isp/ccm_rr").toInt();             //465
    tmp_ccmmatrix[1] = 0x80E1; // settings.value("isp/ccm_rg").toInt();             //32984
    tmp_ccmmatrix[2] = 0x8010; // settings.value("isp/ccm_rb").toInt();             //32775
    tmp_ccmmatrix[3] = 0x8076; // settings.value("isp/ccm_gr").toInt();             //32832
    tmp_ccmmatrix[4] = 0x01B8; // settings.value("isp/ccm_gg").toInt();             //449
    tmp_ccmmatrix[5] = 0x8042; // settings.value("isp/ccm_gb").toInt();             //32897
    tmp_ccmmatrix[6] = 0x803D; // settings.value("isp/ccm_br").toInt();             //1
    tmp_ccmmatrix[7] = 0x8146; // settings.value("isp/ccm_bg").toInt();             //32959
    tmp_ccmmatrix[8] = 0x0283; // settings.value("isp/ccm_bb").toInt();             //446
    //=======================================================================================================
    mppIsp_AUTO_EXPOSURE(0, 0);
    mppIspAwb(0, 2, 5500, 300, 280, 280, 430);
    mppIspSharpen(0, 2, 1000, 2000, 20, 30, 225, 16, 115, 16, 127, 96, 100, 8, 9, 128, 160, 53, 28, 32, 28, 23, 160);
    mppIspGammaCtrl(0, 0, 1);
}

//=======================================================================================================
//显示尺寸缩放设置,(USE in QT-->camer_ops.cpp)
//=======================================================================================================
HI_S32 mppDisplayResize(SAMPLE_VI_CONFIG_S stViConfig, SAMPLE_VO_CONFIG_S stVoConfig, int disWidth, int disHeight)
{
    viVpssInit(stViConfig, disWidth, disHeight);
    if(stViConfig.astViInfo[0].stSnsInfo.s32SnsId)
        mppIsp_AUTO_EXPOSURE(0,2);                              //DVP摄像头为bypass曝光模式;
    else
        mppIsp_AUTO_EXPOSURE(0,0);                              //MIPI摄像头为自动曝光模式;
    SAMPLE_COMM_VO_StopVO(&stVoConfig);
    stVoConfig.stImageSize.u32Width = disWidth;
    stVoConfig.stImageSize.u32Height = disHeight;
    SAMPLE_COMM_VO_StartVO(&stVoConfig);
    return 0;
}

//=======================================================================================================
//解码器 初始化
//=======================================================================================================
HI_S32 vdencVpssInit(int disWidth, int disHeight)
    {
        HI_S32 s32Ret = HI_SUCCESS;
        HI_U32 u32VdecChnNum = 1;
        SAMPLE_VDEC_ATTR stSampleVdec;
        VPSS_GRP_ATTR_S stVpssGrpAttr;
        VPSS_CHN_ATTR_S stVpssChnAttr;
        MPP_CHN_S stSrcChn;
        MPP_CHN_S stDestChn;
        MPP_CHN_S stDestChn1;
        stSampleVdec.enType = PT_H265;
        stSampleVdec.u32Width = disWidth;
        stSampleVdec.u32Height = disHeight;
        stSampleVdec.enMode = VIDEO_MODE_FRAME;
        stSampleVdec.stSapmleVdecVideo.enDecMode = VIDEO_DEC_MODE_IP;
        stSampleVdec.stSapmleVdecVideo.enBitWidth = DATA_BITWIDTH_8;
        stSampleVdec.stSapmleVdecVideo.u32RefFrameNum = 2;
        stSampleVdec.u32DisplayFrameNum = 2;
        stSampleVdec.u32FrameBufCnt = stSampleVdec.stSapmleVdecVideo.u32RefFrameNum + stSampleVdec.u32DisplayFrameNum + 1;
        SAMPLE_COMM_VDEC_InitVBPool(u32VdecChnNum, &stSampleVdec);
        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("init mod common vb fail for %#x!\n", s32Ret);
            return -1;
        }
        SAMPLE_COMM_VDEC_Start(u32VdecChnNum, &stSampleVdec);
        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("start VDEC fail for %#x!\n", s32Ret);
            return -1;
        }
        stVpssGrpAttr.u32MaxW = disWidth;
        stVpssGrpAttr.u32MaxH = disHeight;
        stVpssGrpAttr.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
        stVpssGrpAttr.enDynamicRange = DYNAMIC_RANGE_SDR8;
        stVpssGrpAttr.stFrameRate.s32SrcFrameRate = -1;
        stVpssGrpAttr.stFrameRate.s32DstFrameRate = -1;
        stVpssGrpAttr.bNrEn = HI_FALSE;
        stVpssChnAttr.u32Width = disWidth;
        stVpssChnAttr.u32Height = disHeight;
        stVpssChnAttr.enChnMode = VPSS_CHN_MODE_USER;
        stVpssChnAttr.enCompressMode = COMPRESS_MODE_NONE;
        stVpssChnAttr.enDynamicRange = DYNAMIC_RANGE_SDR8;
        stVpssChnAttr.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
        stVpssChnAttr.stFrameRate.s32SrcFrameRate = -1;
        stVpssChnAttr.stFrameRate.s32DstFrameRate = -1;
        stVpssChnAttr.u32Depth = 0;
        stVpssChnAttr.bMirror = HI_FALSE;
        stVpssChnAttr.bFlip = HI_FALSE;
        stVpssChnAttr.stAspectRatio.enMode = ASPECT_RATIO_NONE;
        stVpssChnAttr.enVideoFormat = VIDEO_FORMAT_LINEAR;
        stSrcChn.enModId = HI_ID_VDEC;
        stSrcChn.s32DevId = 0;
        stSrcChn.s32ChnId = 0;
        stDestChn.enModId = HI_ID_VPSS;
        stDestChn.s32DevId = 0;
        stDestChn.s32ChnId = 1;
        stDestChn1.enModId = HI_ID_VO;
        stDestChn1.s32DevId = 0;
        stDestChn1.s32ChnId = 0;
        CHECK_RET(HI_MPI_VPSS_CreateGrp(0, &stVpssGrpAttr), "HI_MPI_VPSS_CreateGrp(0)");
        CHECK_RET(HI_MPI_VPSS_SetChnAttr(0, 1, &stVpssChnAttr), "HI_MPI_VPSS_SetChnAttr(0,1)");
        CHECK_RET(HI_MPI_VPSS_EnableChn(0, 1), "HI_MPI_VPSS_EnableChn(0,1)");
        CHECK_RET(HI_MPI_VPSS_StartGrp(0), "HI_MPI_VPSS_StartGrp(0)");
        CHECK_RET(HI_MPI_SYS_Bind(&stSrcChn, &stDestChn), "HI_MPI_SYS_Bind(VDEC-VPSS)");
        CHECK_RET(HI_MPI_SYS_Bind(&stDestChn, &stDestChn1), "HI_MPI_SYS_Bind(VPSS-VO)");
        return 0;
    }

//=======================================================================================================
//消毁  ，视频播放结束后，
//=======================================================================================================
HI_S32 vdencVpssDeinit()
    {
        MPP_CHN_S stSrcChn;
        MPP_CHN_S stDestChn;
        MPP_CHN_S stDestChn1;
        stSrcChn.enModId = HI_ID_VDEC;
        stSrcChn.s32DevId = 0;
        stSrcChn.s32ChnId = 0;
        stDestChn.enModId = HI_ID_VPSS;
        stDestChn.s32DevId = 0;
        stDestChn.s32ChnId = 1;
        stDestChn1.enModId = HI_ID_VO;
        stDestChn1.s32DevId = 0;
        stDestChn1.s32ChnId = 0;
        CHECK_RET(HI_MPI_SYS_UnBind(&stDestChn, &stDestChn1), "HI_MPI_SYS_UnBind(VPSS-VO)");
        CHECK_RET(HI_MPI_SYS_UnBind(&stSrcChn, &stDestChn), "HI_MPI_SYS_UnBind(VDEC-VPSS)");
        CHECK_RET(HI_MPI_VPSS_DisableChn(0, 1), "HI_MPI_VPSS_DisableChn(0-1)");
        CHECK_RET(HI_MPI_VPSS_StopGrp(0), "HI_MPI_VPSS_StopGrp(0)");
        CHECK_RET(HI_MPI_VPSS_DestroyGrp(0), "HI_MPI_VPSS_DestroyGrp(0)");
        CHECK_CHN_RET(HI_MPI_VDEC_StopRecvStream(0), 0, "HI_MPI_VDEC_StopRecvStream");
        CHECK_CHN_RET(HI_MPI_VDEC_DestroyChn(0), 0, "HI_MPI_VDEC_DestroyChn");
        HI_MPI_VB_ExitModCommPool(VB_UID_VDEC);
        return HI_SUCCESS;
    }

//=======================================================================================================
//电池初始化
//=======================================================================================================
void initBattery()
    {
        int i2c_file;
        unsigned char inbuf[2];
        struct i2c_rdwr_ioctl_data packets;
        struct i2c_msg messages[1];
        i2c_file = open("/dev/i2c-1", O_RDWR);
        inbuf[0] = 0x0a;
        inbuf[1] = 0x00;
        messages[0].addr = 0x62;
        messages[0].flags = 0;
        messages[0].len = 2;
        messages[0].buf = inbuf;
        packets.msgs = messages;
        packets.nmsgs = 1;
        if (ioctl(i2c_file, I2C_RDWR, &packets) < 0)
        {
            perror("Unable to send data");
        }
        close(i2c_file);
    }

//=======================================================================================================
//获取电量
//=======================================================================================================
int getBattery()
{
        int batteryValue = 100;
        int i2c_file;
        unsigned char inbuf[2];
        struct i2c_rdwr_ioctl_data packets;
        struct i2c_msg messages[2];
        i2c_file = open("/dev/i2c-1", O_RDWR);
        if (i2c_file < 0)
            return 0;
    retry:
        inbuf[0] = 0x02;
        messages[0].addr = 0x62;
        messages[0].flags = 0;
        messages[0].len = 1;
        messages[0].buf = inbuf;
        messages[1].addr = 0x62;
        messages[1].flags = I2C_M_RD /* | I2C_M_NOSTART*/;
        messages[1].len = 2;
        messages[1].buf = inbuf;
        packets.msgs = messages;
        packets.nmsgs = 2;
        if (ioctl(i2c_file, I2C_RDWR, &packets) < 0)
        {
            perror("Unable to send data");
            return 0;
        }
        batteryValue = inbuf[0] << 8 | inbuf[1];
        if (batteryValue == 0)
        {
            usleep(5000);
            goto retry;
        }
        close(i2c_file);
        batteryValue = (batteryValue * 305) / 500;
        // printf("====>电池电量值是：%d <====\r\n",batteryValue);
        return batteryValue;
}

//===================================================================================================================================

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */
